Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle Concurrent Sessions and Saving Readline::HISTORY #651

Merged
merged 7 commits into from
Sep 16, 2023

Conversation

chadrschroeder
Copy link
Contributor

Fixes #510.

@@ -51,7 +51,7 @@ def save_history

if File.exist?(history_file) &&
File.mtime(history_file) != @loaded_history_mtime
history = history[@loaded_history_lines..-1] if @loaded_history_lines
@loaded_history_lines&.times { history.delete_at(0) }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe there's a better way to do this but Readline::HISTORY is pretty limited in how it can be manipulated.

The original issue here was a no implicit conversion of Range into Integer error because Readline::HISTORY doesn't take a range in [].

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unlike the previous code, Reline::HISTORY will be changed in this operation. Maybe it works, but it's safer and easy to maintain if it doesn't change HISTORY object itself.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Updated.

HISTORY = Array.new
class TestInputMethodWithRelineHistory < TestInputMethod
# When IRB.conf[:USE_MULTILINE] is true, IRB::ReidlineInputMethod uses Reline::History
HISTORY = Reline::History.new(Reline.core.config)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed from an Array to the history class that is used by default when :USE_MULTILINE is on.


include IRB::HistorySavingAbility
end

class TestInputMethodWithReadlineHistory < TestInputMethod
# When IRB.conf[:USE_MULTILINE] is false, IRB::ReadlineInputMethod uses Readline::HISTORY
HISTORY = Readline::HISTORY
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created an additional input method test class that uses Readline::HISTORY. At this point, I've only made use of it in the test_history_concurrent_use test method to illustrate the bug. I wasn't sure if we want to test both input methods for all tests.

io.class::HISTORY.clear
io.load_history
io.class::HISTORY.concat(%w"line1 line2")
io.class::HISTORY << 'line1'
io.class::HISTORY << 'line2'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

concat isn't available for Readline::HISTORY. I updated this logic so that this test could use TestInputMethodWithReadlineHistory if we wanted.

yield IRB.rc_file("_history")
io.class::HISTORY.replace(history)
Copy link
Contributor Author

@chadrschroeder chadrschroeder Jul 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Readline::HISTORY doesn't respond to replace. Updated so that this works for both input methods. It's also assigned as a constant so it can't just be reassigned or we hit dynamic constant assignment errors.

end
io.class::HISTORY.concat(input.split)
input.split.each { |line| io.class::HISTORY << line }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Readline::HISTORY doesn't respond to concat. Updated how this adds the new lines.

hist = []
from.upto(self.class::HISTORY.size - 1) do |index|
hist << self.class::HISTORY[index].split("\n").join("\\\n")
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code does not look rubyish compared to the original history = history[@loaded_history_lines..-1] if @loaded_history_lines that does not work.
How about changing history to an array first? then it will work fine for Readline::HISTORY too.

def save_history
  history = self.class::HISTORY.to_a

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

class TestInputMethodWithHistory < TestInputMethod
HISTORY = Array.new
class TestInputMethodWithRelineHistory < TestInputMethod
# When IRB.conf[:USE_MULTILINE] is true, IRB::ReidlineInputMethod uses Reline::History
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IRB::ReidlineInputMethodIRB::RelineInputMethod
IRB::ReidlineInputMethod is not used anymore.

Other part of the change in test_history.rb looks great 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Updated.

Copy link
Contributor Author

@chadrschroeder chadrschroeder left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated. Locally I'm getting a lot of test errors from TestIRB::DebugCommandTest, probably related to the changes from master that were merged into this branch. I get the errors in master as well. I haven't dug into why. The CI testing appears to be running successfully.

class TestInputMethodWithHistory < TestInputMethod
HISTORY = Array.new
class TestInputMethodWithRelineHistory < TestInputMethod
# When IRB.conf[:USE_MULTILINE] is true, IRB::ReidlineInputMethod uses Reline::History
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Updated.

hist = []
from.upto(self.class::HISTORY.size - 1) do |index|
hist << self.class::HISTORY[index].split("\n").join("\\\n")
end
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@st0012 st0012 added the bug Something isn't working label Sep 15, 2023
Copy link
Member

@tompng tompng left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good 👍
Thank you

@tompng tompng merged commit 1681ada into ruby:master Sep 16, 2023
24 checks passed
matzbot pushed a commit to ruby/ruby that referenced this pull request Sep 16, 2023
(ruby/irb#651)

* handle concurrent sessions and saving Readline::HISTORY, fixes ruby/irb#510

* separate tests

* don't mutate the HISTORY object on the class

* avoid repeated .to_i calls

* remove intermediary history array

* work with array, fix test comment

---------

ruby/irb@1681ada328

Co-authored-by: Stan Lo <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Development

Successfully merging this pull request may close these issues.

Cannot save to history file in nomultiline mode with concurrent irb session
3 participants