Skip to content

Commit

Permalink
Introduce cd command
Browse files Browse the repository at this point in the history
It's essentially a combination of pushws and popws commands that are
easier to use.

Help message:

```
Usage: cd ([target]|..)

When given an object, cd will move into that object, making it the current context.
When given "..", cd will leave the current context, moving back to the previous context.
When given no arguments, cd will move back to the top-level (main object) context.

Examples:

  cd Foo
  cd Foo.new
  cd @ivar
  cd ..
  cd
```
  • Loading branch information
st0012 committed Jun 16, 2024
1 parent 35de7da commit 4ac5305
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 0 deletions.
47 changes: 47 additions & 0 deletions lib/irb/command/cd.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# frozen_string_literal: true

module IRB
module Command
class CD < Base
category "Workspace"
description "Move into the given object or leave the current context."

help_message(<<~HELP)
Usage: cd ([target]|..)
When given an object, cd will move into that object, making it the current context.
When given "..", cd will leave the current context, moving back to the previous context.
When given no arguments, cd will move back to the top-level (main object) context.
Examples:
cd Foo
cd Foo.new
cd @ivar
cd ..
cd
HELP

def execute(arg)
case arg
when ".."
irb_context.pop_workspace
when ""
# TODO: decide what workspace commands should be kept, and underlying APIs should look like,
# and perhaps add a new API to clear the workspace stack.
prev_workspace = irb_context.pop_workspace
while prev_workspace
prev_workspace = irb_context.pop_workspace
end
else
begin
obj = eval(arg, irb_context.workspace.binding)
irb_context.push_workspace(obj)
rescue StandardError => e
warn "Error: #{e}"
end
end
end
end
end
end
3 changes: 3 additions & 0 deletions lib/irb/default_commands.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
require_relative "command/backtrace"
require_relative "command/break"
require_relative "command/catch"
require_relative "command/cd"
require_relative "command/chws"
require_relative "command/context"
require_relative "command/continue"
Expand Down Expand Up @@ -240,6 +241,8 @@ def load_command(command)
_register_with_aliases(:irb_disable_irb, Command::DisableIrb,
[:disable_irb, NO_OVERRIDE]
)

register(:cd, Command::CD)
end

ExtendCommand = Command
Expand Down
65 changes: 65 additions & 0 deletions test/irb/command/test_cd.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
require "tempfile"
require_relative "../helper"

module TestIRB
class CDTest < IntegrationTestCase
def setup
super

write_ruby <<~'RUBY'
class Foo
class Bar
def bar
"this is bar"
end
end
def foo
"this is foo"
end
end
binding.irb
RUBY
end

def test_cd
out = run_ruby_file do
type "cd Foo"
type "ls"
type "cd Bar"
type "ls"
type "cd .."
type "exit"
end

assert_match(/irb\(Foo\):002>/, out)
assert_match(/Foo#methods: foo/, out)
assert_match(/irb\(Foo::Bar\):004>/, out)
assert_match(/Bar#methods: bar/, out)
assert_match(/irb\(Foo\):006>/, out)
end

def test_cd_moves_top_level_with_no_args
out = run_ruby_file do
type "cd Foo"
type "cd Bar"
type "cd"
type "exit"
end

assert_match(/irb\(Foo::Bar\):003>/, out)
assert_match(/irb\(main\):004>/, out)
end

def test_cd_with_error
out = run_ruby_file do
type "cd Baz"
type "exit"
end

assert_match(/Error: uninitialized constant Baz/, out)
assert_match(/irb\(main\):002>/, out) # the context should not change
end
end
end

0 comments on commit 4ac5305

Please sign in to comment.