@@ -73,7 +73,6 @@ use harp::r_symbol;
7373use harp:: routines:: r_register_routines;
7474use harp:: session:: r_traceback;
7575use harp:: utils:: r_is_data_frame;
76- use harp:: utils:: r_pairlist_any;
7776use harp:: utils:: r_typeof;
7877use harp:: R_MAIN_THREAD_ID ;
7978use libr:: R_BaseNamespace ;
@@ -121,6 +120,8 @@ use crate::startup;
121120use crate :: strings:: lines;
122121use crate :: sys:: console:: console_to_utf8;
123122
123+ static RE_DEBUG_PROMPT : Lazy < Regex > = Lazy :: new ( || Regex :: new ( r"Browse\[\d+\]" ) . unwrap ( ) ) ;
124+
124125/// An enum representing the different modes in which the R session can run.
125126#[ derive( PartialEq , Clone ) ]
126127pub enum SessionMode {
@@ -844,28 +845,26 @@ impl RMain {
844845 let prompt_slice = unsafe { CStr :: from_ptr ( prompt_c) } ;
845846 let prompt = prompt_slice. to_string_lossy ( ) . into_owned ( ) ;
846847
847- // Detect browser prompts by inspecting the `RDEBUG` flag of each
848- // frame on the stack. If ANY of the frames are marked with `RDEBUG`,
849- // then we assume we are in a debug state. We can't just check the
850- // last frame, as sometimes frames are pushed onto the stack by lazy
851- // evaluation of arguments or `tryCatch()` that aren't debug frames,
852- // but we don't want to exit the debugger when we hit these, as R is
853- // still inside a browser state. Should also handle cases like `debug(readline)`
854- // followed by `n`.
855- // https://github.com/posit-dev/positron/issues/2310
856- let frames = harp:: session:: r_sys_frames ( ) . unwrap ( ) ;
857- let browser = r_pairlist_any ( frames. sexp , |frame| {
858- harp:: session:: r_env_is_browsed ( frame) . unwrap ( )
859- } ) ;
848+ // Detect browser prompt by matching the prompt string
849+ // https://github.com/posit-dev/positron/issues/4742.
850+ // There are ways to break this detection, for instance setting
851+ // `options(prompt =, continue = ` to something that looks like
852+ // a browser prompt, or doing the same with `readline()`. We have
853+ // chosen to not support these edge cases.
854+ let browser = RE_DEBUG_PROMPT . is_match ( & prompt) ;
860855
861856 // If there are frames on the stack and we're not in a browser prompt,
862857 // this means some user code is requesting input, e.g. via `readline()`
863858 let user_request = !browser && n_frame > 0 ;
864859
865860 // The request is incomplete if we see the continue prompt, except if
866- // we're in a user request, e.g. `readline("+ ")`
861+ // we're in a user request, e.g. `readline("+ ")`. To guard against
862+ // this, we check that we are at top-level (call stack is empty or we
863+ // have a debug prompt).
867864 let continuation_prompt: String = harp:: get_option ( "continue" ) . try_into ( ) . unwrap ( ) ;
868- let incomplete = !user_request && prompt == continuation_prompt;
865+ let matches_continuation = prompt == continuation_prompt;
866+ let top_level = n_frame == 0 || browser;
867+ let incomplete = matches_continuation && top_level;
869868
870869 return PromptInfo {
871870 input_prompt : prompt,
0 commit comments