# [Rd] meaning of browser(skipCalls=) [and multiple mouse buttons]

Frederick Eaton |reder|k @end|ng |rom o|b@net
Thu Dec 16 05:09:46 CET 2021

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.
>
>    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.
>
>
>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
>   }
>+
>+  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.