inf-ruby
inf-ruby copied to clipboard
Using inf-ruby-console-auto in org-babel
I'm trying to get org-babel
to execute a buffer inside a inf-ruby-console-auto
buffer running a Rails console. But when I run org-babel-execute-buffer
I get an error:
run-ruby-or-pop-to-buffer: Found inf-ruby buffer, but it was created using a different
NAME-COMMAND combination: rails, ‘bundle exec rails console -e test’
I'm looking at the source but don't understand the intention behind it. Why should trying to run some ruby in an existing buffer raise an error? If I remove that unless
it works fine for my purposes at least.
Because it won't run a new process. It can return an existing buffer, but since it was launched differently, that's unlikely to be what the caller expects. It's an implementation shortcut.
The existing buffer is determined by the directory it was launched from. So apparently you are trying to launch two different process from the same directory. That's fairly unusual.
I'm trying to run several code blocks in an org-mode
file using the same process. Normally org-babel
will run each code block in a separate environment unless you specify a session
property. With session
set, org-babel
calls inf-ruby
rather than inf-ruby-console-auto
so there isn't a proper Rails environment. It seems I need to override either org-babel
or inf-ruby
to get my desired result.
@reedlaw Did you ever arrive at a solution for this? I tried to locally remove the error
block from the source you linked, and I compiled inf-ruby.el
. That seemed to work -- I was then able to (1) start an inf-ruby-console-rails
buffer with in my Rails environment and (2) run org-babel-execute-src-block
on a Ruby block that used the Ruby console buffer. While this is working for me in this specific case I don't know what the implications are of removing that code.
The implications are you might try to launch a new command, in a different environment, but if there is an existing inf-ruby buffer, it will simply be used, discarding the fact that you use a different command.
I'm not sure how org-babel works, but this could probably be fixed in there, without you having to delete the error statement.
Understood, thanks for clarifying. You might be right that org-babel could be changed to address this, but I'm not exactly sure how (sorry, elisp newbie). I think this is the relevant code https://code.orgmode.org/bzg/org-mode/src/master/lisp/ob-ruby.el#L151-L166
You can tell org-babel to use an existing rails session by pointing it to the inf-ruby buffer where that session is running. It fails with the reported error, however.
Edit: Actually, now that I have taken a closer look at the ob-ruby source, it looks like the session name is then interpolated between two asterisks https://code.orgmode.org/bzg/org-mode/src/master/lisp/ob-ruby.el#L159
And changing the org source code block header from :session *rails*
to :session rails
seems to do the trick (the inf-ruby buffer name is *rails*
).
@bi1yeu The code in question seems to have its own session tracking. And even when there is an existing Ruby process running, just because org-babel didn't start it, it tries to create a new one, which fails because an existing buffer was created with a different command. Instead, it can look for an existing buffer first, and just use it.
You can file a bug report/feature request with Org.
Do you really think that nothing could be improved in inf-ruby? In this case the following ugly workaround is possible in Org:
diff --git a/lisp/org/ob-ruby.el b/lisp/org/ob-ruby.el
index 1b8088eaee..559de16a63 100644
--- a/lisp/org/ob-ruby.el
+++ b/lisp/org/ob-ruby.el
@@ -157,7 +167,8 @@ org-babel-ruby-initiate-session
inf-ruby-implementations)))
(buffer (get-buffer (format "*%s*" session)))
(session-buffer (or buffer (save-window-excursion
- (run-ruby cmd session)
+ (let (inf-ruby-buffer inf-ruby-buffers)
+ (run-ruby cmd session))
(current-buffer)))))
(if (org-babel-comint-buffer-livep session-buffer)
(progn (sit-for .25) session-buffer)
It just ignores the existing inf-ruby buffers that are irrelevant to Org sessions, because the buffer names for Org sessions should be defined by the Org header argument :session
.
BTW, a related question: do you think it would be feasible to refactor inf-ruby that it could have a new separate function that returns the command that could be used to run console, but without immediate running it? I'm thinking about adding another header argument :console
to Org. Then in case of presence of :console rails
in Org files ob-ruby.el could call such a function that will return the console command, and ob-ruby.el could use it to run a session. Because currently it should be possible to set the header argument :ruby
to the command discussed on Org list. But the console command is usually too long to write in Org files, e.g. :ruby "bundle exec rails console -e development"
. It would be shorter to write just :console auto
in Org files. Then it could be used with such patch:
@@ -147,4 +157,5 @@ org-babel-ruby-initiate-session
(unless (string= session "none")
(require 'inf-ruby)
- (let* ((cmd (cdr (assoc inf-ruby-default-implementation
- inf-ruby-implementations)))
+ (let* ((cmd (cdr (or (and (assq :console params) ;; e.g. `auto' or `rails'
+ (fboundp 'inf-ruby-console-command)
+ (inf-ruby-console-command (assq :console params)))
(assoc inf-ruby-default-implementation
+ inf-ruby-implementations))))
Do you really think that nothing could be improved in inf-ruby?
Maybe something could. In any case, someone should first try to implement correct behavior in Org.
In this case the following ugly workaround is possible in Org:
This will make it always create a new session/buffer, right? Is that the desired behavior?
BTW, a related question: do you think it would be feasible to refactor inf-ruby that it could have a new separate function that returns the command that could be used to run console
But there are multiple functions now, used to run different kinds of consoles.
To answer the question: perhaps. But that sounds like a fair amount of work.
Maybe something could. In any case, someone should first try to implement correct behavior in Org.
The patch above implements correct behavior in Org, but it uses ugly hack because of current limitations in inf-ruby.
In this case the following ugly workaround is possible in Org:
This will make it always create a new session/buffer, right? Is that the desired behavior?
The desired behavior is to use the same buffer name as the value of header argument :session
. It creates one buffer per session. It's often necessary to have more than one session process in the same project root directory: for example, after switching to another branch, the org file should be able to run another session process for another feature branch. This should be possible by using different :session
header arg in different org files, e.g. :session project1-feature1
, :session project1-feature2
, etc.
BTW, a related question: do you think it would be feasible to refactor inf-ruby that it could have a new separate function that returns the command that could be used to run console
But there are multiple functions now, used to run different kinds of consoles.
To answer the question: perhaps. But that sounds like a fair amount of work.
Should I create a separate issue for this?
The desired behavior is to use the same buffer name as the value of header argument :session. It creates one buffer per session.
Does it try to run consoles using different commands in the same named buffer? What is the general expectation when such a buffer exists but it was launched using a different command?
Should I create a separate issue for this?
Yes, please. A prototype patch also wouldn't hurt.
The desired behavior is to use the same buffer name as the value of header argument :session. It creates one buffer per session.
Does it try to run consoles using different commands in the same named buffer?
No different console commands needed for the same buffer.
What is the general expectation when such a buffer exists but it was launched using a different command?
It's highly unlikely that an undesirable buffer exists with the same session name because choosing session naming should be under user's control.
Should I create a separate issue for this?
Yes, please. A prototype patch also wouldn't hurt.
Created a new issue in #138.
No different console commands needed for the same buffer.
The error described in the description of this issue happens when two different consoles have been attempted to launch in the same buffer. inf-ruby
compares the commands, sees they are different, and raises the error.
Looking at this discussion again, sounds like it should be fixed in Org. In particular, this logic:
Normally org-babel will run each code block in a separate environment unless you specify a session property. With session set, org-babel calls inf-ruby rather than inf-ruby-console-auto so there isn't a proper Rails environment.
Just call the same command again. Or, if you want to reuse the :session
value, search for the buffer among existing ones, and if it's live, pop to it.
The root of the problem is at the end of the function run-ruby
:
(or (inf-ruby-buffer)
inf-ruby-buffer)))
It always insists on using the existing buffer, even when the user asked for a different buffer by using a different argument name
of the function call run-ruby
.
It operates on a particular project-finding logic (codified in inf-ruby-buffer
, among other places) and an assumption that the user wouldn't really want to have two different consoles in the same project by accident. Or create a new console by accident rather than switch to an existing one.
It's a relatively new development; previously, inf-ruby
silently returned the one existing buffer if it was still live, no matter whether the command matched.
Can org-babel find its buffer based on the value of :session
? Then it could call run-ruby-or-pop-to-buffer
.
Great, this is exactly what is needed! Do you see a problem with such a patch?
diff --git a/lisp/org/ob-ruby.el b/lisp/org/ob-ruby.el
index aa28bf1899..0fbd4ecbb7 100644
--- a/lisp/org/ob-ruby.el
+++ b/lisp/org/ob-ruby.el
@@ -159,7 +164,10 @@ org-babel-ruby-initiate-session
inf-ruby-implementations))))
(buffer (get-buffer (format "*%s*" session)))
(session-buffer (or buffer (save-window-excursion
- (run-ruby cmd session)
+ (run-ruby-or-pop-to-buffer
+ cmd (or session "ruby")
+ (unless session
+ (inf-ruby-buffer)))
(current-buffer)))))
(if (org-babel-comint-buffer-livep session-buffer)
(progn (sit-for .25) session-buffer)
I'm not sure I understand the intention in that patch.
When session
is non-nil, ob-ruby should find the corresponding buffer and pass it as BUFFER to run-ruby-or-pop-to-buffer
. That's the point of session
's value, no? And your patch passes nil
in that case.
When get-buffer
returns non-nil existing buffer, and sets buffer
, then this is used for session-buffer
without calling run-ruby-or-pop-to-buffer
. If no buffer found then it's created with the help of run-ruby-or-pop-to-buffer
.
Ah. Then you probably want to call run-ruby-new
directly.
It's still needed to use run-ruby-or-pop-to-buffer
because when session
is nil
, then better to reuse the same buffer from the same root dir (returned by the function inf-ruby-buffer
), i.e. to use the 3rd arg of run-ruby-or-pop-to-buffer
that you can see in the patch above.
Maybe you're right. Will it save the found buffer's name to the session
property?
Why would it do this? The users explicitly asked session
to be nil
to reuse the buffer corresponding to nil
among other code blocks where session
is nil
.
I see. If that's the intention.
But run-ruby-or-pop-to-buffer
does the check that this bug report complains about: compares the intended command name and implementation name to the ones in the found buffer. And raises an error if they don't match. And I think it's a reasonable expectation - when you're invoking a Ruby console with a particular command, a buffer that pops up must have been launched with the said command.
If you don't want that check, ob-ruby
will have to write its own version of run-ruby-or-pop-to-buffer
. It's not hard, though: just a few lines.
I see no problem with checking command names in run-ruby-or-pop-to-buffer. If a user uses different commands in case of nil session
then it's fine to check that the commands should be the same.
For example, if one code block uses
:session :ruby "bundle exec rails console -e development"
but another code block uses
:session :ruby "bundle exec rails console -e test"
then it would the right thing to raise the error that commands are different to avoid damage of code execution in the wrong environment.
However, when the user gives names to :session
then it should be user's responsibility to name sessions accordingly, e.g. :session development
and :session test
.
I see no problem with checking command names in run-ruby-or-pop-to-buffer.
It was my understanding that it's the source of the original complaint in this issue.
But if you can reproduce that problem, and your patch fixes it, then all the better.
Looks like this got fixed in ob-ruby.