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.