Frederick Eaton
2021-Dec-08 08:24 UTC
[Rd] meaning of browser(skipCalls=) [and multiple mouse buttons]
Dear R Core Team, I'm attaching a proposed patch to hopefully address my confusions regarding the documentation of browser(). I'm not sure if all the material I added is correct, but I made experiments to confirm that the behavior is at least roughly as described. patch ./src/library/base/man/browser.Rd < browser.patch Also, here is a patch to support multiple mouse buttons in getGraphicsEvent(). This must be edited before it can be applied, I decided to keep the old code in an 'if(0)' to help make it clearer that my code is essentially doing the same thing. https://github.com/navarum/tweaks/blob/master/r/patches/0001-Add-support-for-multiple-mouse-buttons.patch wget -O - https://raw.githubusercontent.com/navarum/tweaks/master/r/patches/0001-Add-support-for-multiple-mouse-buttons.patch | patch -p1 It would be useful to have support in R for more than three mouse buttons because this enables the use of the mouse wheel (buttons 4 and 5), which can provide a more convenient interface when adjusting numbers and graphics and so on. I also have shift+wheel bound to buttons 6 and 7 via xbindkeys and xte, which I use for horizontal scrolling, via a trick from the web somewhere: $ cat .xbindkeysrc.scm | grep xte (xbindkey '(shift "b:4") "xte 'mouseclick 6'") (xbindkey '(shift "b:5") "xte 'mouseclick 7'") I hope that these contributions can be found acceptable. Thank you in advance, Frederick On Mon, Nov 22, 2021 at 09:13:58AM -0800, Frederick Eaton wrote:>Dear R Devel, > >I have been advised to use "options(error=recover)" to enable >debugging on errors. But sometimes it would seem more convenient to >override "stopifnot", for example: > > stopifnot = function(b) { if(!b) { browser(skipCalls=1); } } > >However, this doesn't do what I expected. On looking closer I find >that the "skipCalls" argument seems to be ignored except when printing >the "Called from: " message; it does not affect the evaluation context >or the output of 'where': > > > var=2; f=function(){var=1; browser(skipCalls=0)}; f() > Called from: f() > Browse[1]> var > [1] 1 > Browse[1]> where > where 1: f() > > Browse[1]> Q > > var=2; f=function(){var=1; browser(skipCalls=1)}; f() > Called from: top level Browse[1]> var > [1] 1 > Browse[1]> where > where 1: f() > > Browse[1]> Q > > var=2; f=function(){var=1; browser(skipCalls=2)}; f() > Called from: top level Browse[1]> var > [1] 1 > Browse[1]> where > where 1: f() > > Browse[1]> Q > >So it appears that the "browser()" API does not actually make it >possible to call this built-in function from within another R function >and thereby emulate the same behavior as calling browser() directly. > >If this is the case, it might be good to have it fixed or documented. >I am aware of "browser(expr=)", but this requires editing the >particular call that failed. The documentation for "browser()" led me >to hope that my use case would be supported, if only because it admits >that users might want to build other debugging functions with >browser(): "The 'skipCalls' argument should be used when the >'browser()' call is nested within another debugging function". An >example where this 'skipCalls' parameter is used to build a useful >debugging function would help to clarify its English description in >the manual. > >Also, from the browser() command line I could not find a way to step >*out* of the current function. This would have been a way to recover >from skipCalls not working as expected. Am I missing something? For >example is there some command other than "n", where the below >interaction could pause before "hi" and "bye"? > > > f=function(){browser(); message("in f"); message("out f")}; f(); message("hi"); message("bye") > Called from: f() > Browse[1]> n > debug at #1: message("in f") > Browse[2]> n > in f > debug at #1: message("out f") > Browse[2]> n > out f > hi > bye > >If it is not possible for the R debugger to step out of a function, it >would be good to document that too, maybe after the list of browser >prompt commands in "?browser". Being confined within a single function >is not an obvious disability for a debugger to have. > >I feel that R is an excellent tool, but sometimes I think that if the >shortcomings of the system were better documented, then this would >save users a lot of time in certain cases. > >Thank you, > >Frederick >-------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: browser.patch URL: <https://stat.ethz.ch/pipermail/r-devel/attachments/20211208/056037de/attachment.ksh>
Frederick Eaton
2021-Dec-16 04:09 UTC
[Rd] meaning of browser(skipCalls=) [and multiple mouse buttons]
Just following up to check if anyone has had time to look over these patches. Frederick On Wed, Dec 08, 2021 at 12:24:47AM -0800, Frederick Eaton wrote:>Dear R Core Team, > >I'm attaching a proposed patch to hopefully address my confusions regarding the documentation of browser(). I'm not sure if all the material I added is correct, but I made experiments to confirm that the behavior is at least roughly as described. > > patch ./src/library/base/man/browser.Rd < browser.patch > >Also, here is a patch to support multiple mouse buttons in getGraphicsEvent(). This must be edited before it can be applied, I decided to keep the old code in an 'if(0)' to help make it clearer that my code is essentially doing the same thing. > > https://github.com/navarum/tweaks/blob/master/r/patches/0001-Add-support-for-multiple-mouse-buttons.patch > wget -O - https://raw.githubusercontent.com/navarum/tweaks/master/r/patches/0001-Add-support-for-multiple-mouse-buttons.patch | patch -p1 > >It would be useful to have support in R for more than three mouse buttons because this enables the use of the mouse wheel (buttons 4 and 5), which can provide a more convenient interface when adjusting numbers and graphics and so on. I also have shift+wheel bound to buttons 6 and 7 via xbindkeys and xte, which I use for horizontal scrolling, via a trick from the web somewhere: > > $ cat .xbindkeysrc.scm | grep xte > (xbindkey '(shift "b:4") "xte 'mouseclick 6'") > (xbindkey '(shift "b:5") "xte 'mouseclick 7'") > >I hope that these contributions can be found acceptable. > >Thank you in advance, > >Frederick > > > >On Mon, Nov 22, 2021 at 09:13:58AM -0800, Frederick Eaton wrote: >>Dear R Devel, >> >>I have been advised to use "options(error=recover)" to enable >>debugging on errors. But sometimes it would seem more convenient to >>override "stopifnot", for example: >> >> stopifnot = function(b) { if(!b) { browser(skipCalls=1); } } >> >>However, this doesn't do what I expected. On looking closer I find >>that the "skipCalls" argument seems to be ignored except when printing >>the "Called from: " message; it does not affect the evaluation context >>or the output of 'where': >> >> > var=2; f=function(){var=1; browser(skipCalls=0)}; f() >> Called from: f() >> Browse[1]> var >> [1] 1 >> Browse[1]> where >> where 1: f() >> >> Browse[1]> Q >> > var=2; f=function(){var=1; browser(skipCalls=1)}; f() >> Called from: top level Browse[1]> var >> [1] 1 >> Browse[1]> where >> where 1: f() >> >> Browse[1]> Q >> > var=2; f=function(){var=1; browser(skipCalls=2)}; f() >> Called from: top level Browse[1]> var >> [1] 1 >> Browse[1]> where >> where 1: f() >> >> Browse[1]> Q >> >>So it appears that the "browser()" API does not actually make it >>possible to call this built-in function from within another R function >>and thereby emulate the same behavior as calling browser() directly. >> >>If this is the case, it might be good to have it fixed or documented. >>I am aware of "browser(expr=)", but this requires editing the >>particular call that failed. The documentation for "browser()" led me >>to hope that my use case would be supported, if only because it admits >>that users might want to build other debugging functions with >>browser(): "The 'skipCalls' argument should be used when the >>'browser()' call is nested within another debugging function". An >>example where this 'skipCalls' parameter is used to build a useful >>debugging function would help to clarify its English description in >>the manual. >> >>Also, from the browser() command line I could not find a way to step >>*out* of the current function. This would have been a way to recover >>from skipCalls not working as expected. Am I missing something? For >>example is there some command other than "n", where the below >>interaction could pause before "hi" and "bye"? >> >> > f=function(){browser(); message("in f"); message("out f")}; f(); message("hi"); message("bye") >> Called from: f() >> Browse[1]> n >> debug at #1: message("in f") >> Browse[2]> n >> in f >> debug at #1: message("out f") >> Browse[2]> n >> out f >> hi >> bye >> >>If it is not possible for the R debugger to step out of a function, it >>would be good to document that too, maybe after the list of browser >>prompt commands in "?browser". Being confined within a single function >>is not an obvious disability for a debugger to have. >> >>I feel that R is an excellent tool, but sometimes I think that if the >>shortcomings of the system were better documented, then this would >>save users a lot of time in certain cases. >> >>Thank you, >> >>Frederick >>>--- browser-orig.Rd 2021-12-07 22:35:51.991222137 -0800 >+++ browser-new.Rd 2021-12-07 23:53:36.414106296 -0800 >@@ -45,8 +45,16 @@ > will be simpler. > > The \code{skipCalls} argument should be used when the \code{browser()} >- call is nested within another debugging function: it will look further >- up the call stack to report its location. >+ call is nested within another debugging function: it will look further >+ up the call stack to report its location. However, currently this >+ argument only affects the \code{Called from:} message printed before >+ the first \code{Browse>} prompt, and does not change the evaluation >+ environment of the expressions entered there, nor the output of the >+ \code{where} command. It is not clear when this argument would be >+ useful. It is for example currently impossible to change occurrences >+ of \code{stopifnot(x)} to act like \code{browser(expr=!x)} by >+ redefining \code{stopifnot()}; this must instead be done through a >+ textual search-and-replace or \code{options(error=recover)}. > > At the browser prompt the user can enter commands or \R expressions, > followed by a newline. The commands are >@@ -58,11 +66,9 @@ > \item{\code{f}}{finish execution of the current loop or function} > \item{\code{help}}{print this list of commands} > \item{\code{n}}{evaluate the next statement, stepping over >- function calls. For byte compiled functions interrupted by >- \code{browser} calls, \code{n} is equivalent to \code{c}.} >+ function calls.} > \item{\code{s}}{evaluate the next statement, stepping into >- function calls. Again, byte compiled functions make >- \code{s} equivalent to \code{c}.} >+ function calls.} > \item{\code{where}}{print a stack trace of all active function calls.} > \item{\code{r}}{invoke a \code{"resume"} restart if one is > available; interpreted as an \R expression otherwise. Typically >@@ -71,6 +77,15 @@ > \item{\code{Q}}{exit the browser and the current evaluation and > return to the top-level prompt.} > } >+ >+ Both \code{n} and \code{s} also step out of function calls. However, >+ it is currently not possible with these commands to step out of the >+ function which called \code{browser()}. At the end of the function >+ which called \code{browser}, \code{n} and \code{s} are both equivalent >+ to \code{c}. These commands (\code{n} and \code{s}) are also >+ equivalent to \code{c} when trying to use them inside byte compiled >+ functions interrupted by \code{browser} calls. >+ > Leading and trailing whitespace is ignored, except for an empty line. > Handling of empty lines depends on the \code{"browserNLdisabled"} > \link[=options]{option}; if it is \code{TRUE}, empty lines are ignored.