diff --git a/IPython/extensions/rmagic.py b/IPython/extensions/rmagic.py index 3f6500e..453d78c 100644 --- a/IPython/extensions/rmagic.py +++ b/IPython/extensions/rmagic.py @@ -184,20 +184,28 @@ class RMagics(Magics): def eval(self, line): ''' - Parse and evaluate a line with rpy2. - Returns the output to R's stdout() connection - and the value of eval(parse(line)). + Parse and evaluate a line of R code with rpy2. + Returns the output to R's stdout() connection, + the value generated by evaluating the code, and a + boolean indicating whether the return value would be + visible if the line of code were evaluated in an R REPL. + + R Code evaluation and visibility determination are + done via an R call of the form withVisible({}) + ''' old_writeconsole = ri.get_writeconsole() ri.set_writeconsole(self.write_console) try: - value = ri.baseenv['eval'](ri.parse(line)) + res = ro.r("withVisible({%s})" % line) + value = res[0] #value (R object) + visible = ro.conversion.ri2py(res[1])[0] #visible (boolean) except (ri.RRuntimeError, ValueError) as exception: warning_or_other_msg = self.flush() # otherwise next return seems to have copy of error raise RInterpreterError(line, str_to_unicode(str(exception)), warning_or_other_msg) text_output = self.flush() ri.set_writeconsole(old_writeconsole) - return text_output, value + return text_output, value, visible def write_console(self, output): ''' @@ -413,13 +421,16 @@ class RMagics(Magics): In [9]: %R X=c(1,4,5,7); sd(X); mean(X) Out[9]: array([ 4.25]) - As a cell, this will run a block of R code, without bringing anything back by default:: + In cell mode, this will run a block of R code. The resulting value + is printed if it would printed be when evaluating the same code + within a standard R REPL. + + Nothing is returned to python by default in cell mode. In [10]: %%R ....: Y = c(2,4,3,9) - ....: print(summary(lm(Y~X))) - ....: - + ....: summary(lm(Y~X)) + Call: lm(formula = Y ~ X) @@ -580,14 +591,20 @@ class RMagics(Magics): try: if line_mode: for line in code.split(';'): - text_result, result = self.eval(line) + text_result, result, visible = self.eval(line) text_output += text_result if text_result: # the last line printed something to the console so we won't return it return_output = False else: - text_result, result = self.eval(code) + text_result, result, visible = self.eval(code) text_output += text_result + if visible: + old_writeconsole = ri.get_writeconsole() + ri.set_writeconsole(self.write_console) + ro.r.show(result) + text_output += self.flush() + ri.set_writeconsole(old_writeconsole) except RInterpreterError as e: print(e.stdout)