summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyrylo Silin <silin@kyrylo.org>2019-04-29 23:56:54 +0300
committerGitHub <noreply@github.com>2019-04-29 23:56:54 +0300
commitaf1c0664df0fc043ba27b32f6b7d376ab7bae6a9 (patch)
treed6982760662e317f9ba28fb2e66e64bae5145e6d
parentba18ef32adf0c43bfe4130251b612be44513d990 (diff)
parentaab6431559631b3d48cb0106feaf04e0c242b507 (diff)
downloadpry-af1c0664df0fc043ba27b32f6b7d376ab7bae6a9.tar.gz
Merge pull request #2020 from pry/command-global-state
pry_instance: factor out command state to be global
-rw-r--r--lib/pry.rb1
-rw-r--r--lib/pry/command.rb6
-rw-r--r--lib/pry/command_state.rb29
-rw-r--r--lib/pry/control_d_handler.rb4
-rw-r--r--lib/pry/pry_instance.rb2
-rw-r--r--spec/command_spec.rb12
-rw-r--r--spec/command_state_spec.rb47
-rw-r--r--spec/commands/cd_spec.rb10
-rw-r--r--spec/commands/shell_command_spec.rb4
-rw-r--r--spec/control_d_handler_spec.rb2
10 files changed, 100 insertions, 17 deletions
diff --git a/lib/pry.rb b/lib/pry.rb
index 3b4bcfe1..fbbaa2ab 100644
--- a/lib/pry.rb
+++ b/lib/pry.rb
@@ -24,6 +24,7 @@ require 'pry/color_printer'
require 'pry/exception_handler'
require 'pry/system_command_handler'
require 'pry/control_d_handler'
+require 'pry/command_state'
Pry::Commands = Pry::CommandSet.new unless defined?(Pry::Commands)
diff --git a/lib/pry/command.rb b/lib/pry/command.rb
index 81cded01..fa6d2e51 100644
--- a/lib/pry/command.rb
+++ b/lib/pry/command.rb
@@ -196,6 +196,10 @@ class Pry
end
end
end
+
+ def state
+ Pry::CommandState.default.state_for(match)
+ end
end
# Properties of one execution of a command (passed by {Pry#run_command} as a hash of
@@ -305,7 +309,7 @@ class Pry
# state.my_state = "my state" # this will not conflict with any
# # `state.my_state` used in another command.
def state
- pry_instance.command_state[match] ||= Pry::Config.from_hash({})
+ self.class.state
end
# Revaluate the string (str) and perform interpolation.
diff --git a/lib/pry/command_state.rb b/lib/pry/command_state.rb
new file mode 100644
index 00000000..263d14d8
--- /dev/null
+++ b/lib/pry/command_state.rb
@@ -0,0 +1,29 @@
+require 'ostruct'
+
+class Pry
+ # CommandState is a data structure to hold per-command state.
+ #
+ # Pry commands can store arbitrary state here. This state persists between
+ # subsequent command invocations. All state saved here is unique to the
+ # command.
+ #
+ # @since ?.?.?
+ # @api private
+ class CommandState
+ def self.default
+ @default ||= new
+ end
+
+ def initialize
+ @command_state = {}
+ end
+
+ def state_for(command_name)
+ @command_state[command_name] ||= OpenStruct.new
+ end
+
+ def reset(command_name)
+ @command_state[command_name] = OpenStruct.new
+ end
+ end
+end
diff --git a/lib/pry/control_d_handler.rb b/lib/pry/control_d_handler.rb
index d02e2110..1021c767 100644
--- a/lib/pry/control_d_handler.rb
+++ b/lib/pry/control_d_handler.rb
@@ -16,8 +16,8 @@ class Pry
else
# Otherwise, saves current binding stack as old stack and pops last
# binding out of binding stack (the old stack still has that binding).
- pry_instance.command_state['cd'] ||= Pry::Config.from_hash({})
- pry_instance.command_state['cd'].old_stack = pry_instance.binding_stack.dup
+ cd_state = Pry::CommandState.default.state_for('cd')
+ cd_state.old_stack = pry_instance.binding_stack.dup
pry_instance.binding_stack.pop
end
end
diff --git a/lib/pry/pry_instance.rb b/lib/pry/pry_instance.rb
index 9269ded7..e1309ce9 100644
--- a/lib/pry/pry_instance.rb
+++ b/lib/pry/pry_instance.rb
@@ -34,7 +34,6 @@ class Pry
attr_accessor :last_dir
attr_reader :last_exception
- attr_reader :command_state
attr_reader :exit_value
# @since v0.12.0
@@ -72,7 +71,6 @@ class Pry
def initialize(options = {})
@binding_stack = []
@indent = Pry::Indent.new
- @command_state = {}
@eval_string = ""
@backtrace = options.delete(:backtrace) || caller
target = options.delete(:target)
diff --git a/spec/command_spec.rb b/spec/command_spec.rb
index f56d92db..b01cff07 100644
--- a/spec/command_spec.rb
+++ b/spec/command_spec.rb
@@ -416,6 +416,12 @@ RSpec.describe Pry::Command do
end
end
+ describe ".state" do
+ it "returns a command state" do
+ expect(described_class.state).to be_an(OpenStruct)
+ end
+ end
+
describe "#run" do
let(:command_set) do
set = Pry::CommandSet.new
@@ -475,12 +481,12 @@ RSpec.describe Pry::Command do
subject { Class.new(described_class).new(pry_instance: Pry.new) }
it "returns a state hash" do
- expect(subject.state).to be_a(Pry::Config)
+ expect(subject.state).to be_an(OpenStruct)
end
it "remembers the state" do
- subject.state[:foo] = :bar
- expect(subject.state[:foo]).to eq(:bar)
+ subject.state.foo = :bar
+ expect(subject.state.foo).to eq(:bar)
end
end
diff --git a/spec/command_state_spec.rb b/spec/command_state_spec.rb
new file mode 100644
index 00000000..10097b2b
--- /dev/null
+++ b/spec/command_state_spec.rb
@@ -0,0 +1,47 @@
+RSpec.describe Pry::CommandState do
+ describe ".default" do
+ it "returns the default command state" do
+ expect(described_class.default).to be_a(described_class)
+ end
+
+ context "when called multiple times" do
+ it "returns the same command state" do
+ first_state = described_class.default
+ second_state = described_class.default
+ expect(first_state).to eql(second_state)
+ end
+ end
+ end
+
+ describe "#state_for" do
+ it "returns a state for the matching command" do
+ subject.state_for('command').foobar = 1
+ expect(subject.state_for('command').foobar).to eq(1)
+ end
+
+ it "returns new state for new command" do
+ expect(subject.state_for('command'))
+ .not_to equal(subject.state_for('other-command'))
+ end
+
+ it "memoizes state for the same command" do
+ expect(subject.state_for('command')).to equal(subject.state_for('command'))
+ end
+ end
+
+ describe "#reset" do
+ it "resets the command state for the given command" do
+ subject.state_for('command').foobar = 1
+ subject.reset('command')
+ expect(subject.state_for('command').foobar).to be_nil
+ end
+
+ it "doesn't reset command state for other commands" do
+ subject.state_for('command').foobar = 1
+ subject.state_for('other-command').foobar = 1
+ subject.reset('command')
+
+ expect(subject.state_for('other-command').foobar).to eq(1)
+ end
+ end
+end
diff --git a/spec/commands/cd_spec.rb b/spec/commands/cd_spec.rb
index d2120a6e..38830ace 100644
--- a/spec/commands/cd_spec.rb
+++ b/spec/commands/cd_spec.rb
@@ -16,20 +16,16 @@ describe 'cd' do
end
def command_state
- pry.command_state["cd"]
+ pry.commands['cd'].state
end
def old_stack
- pry.command_state['cd'].old_stack.dup
+ pry.commands['cd'].state.old_stack.dup
end
end
end
- describe 'state' do
- it 'should not to be set up in fresh instance' do
- expect(@t.command_state).to equal nil
- end
- end
+ after { Pry::CommandState.default.reset('cd') }
describe 'old stack toggling with `cd -`' do
describe 'in fresh pry instance' do
diff --git a/spec/commands/shell_command_spec.rb b/spec/commands/shell_command_spec.rb
index 4417f0ee..62526b3c 100644
--- a/spec/commands/shell_command_spec.rb
+++ b/spec/commands/shell_command_spec.rb
@@ -5,11 +5,13 @@ describe Pry::Command::ShellCommand do
@t = pry_tester(@o) do
def command_state
- pry.command_state[Pry::Command::ShellCommand.match]
+ Pry::CommandState.default.state_for(Pry::Command::ShellCommand.match)
end
end
end
+ after { Pry::CommandState.default.reset(Pry::Command::ShellCommand.match) }
+
describe ".cd" do
before do
allow(Dir).to receive(:chdir)
diff --git a/spec/control_d_handler_spec.rb b/spec/control_d_handler_spec.rb
index 2c5a45ae..5e21ccbe 100644
--- a/spec/control_d_handler_spec.rb
+++ b/spec/control_d_handler_spec.rb
@@ -37,7 +37,7 @@ RSpec.describe Pry::ControlDHandler do
it "saves a dup of the current binding stack in the 'cd' command" do
described_class.default(eval_string, pry_instance)
- cd_state = pry_instance.command_state['cd']
+ cd_state = pry_instance.commands['cd'].state
expect(cd_state.old_stack).to eq([binding1, binding2])
end