[education/rkward] /: Cleanup

Thomas Friedrichsmeier null at kde.org
Wed Sep 3 06:48:52 BST 2025


Git commit d79a1bf729203ca80165f83fcb2cc75513e78c0b by Thomas Friedrichsmeier.
Committed on 02/09/2025 at 05:51.
Pushed by tfry into branch 'master'.

Cleanup

M  +1    -1    INSTALL
M  +18   -22   rkward/rbackend/rkrbackend.cpp

https://invent.kde.org/education/rkward/-/commit/d79a1bf729203ca80165f83fcb2cc75513e78c0b

diff --git a/INSTALL b/INSTALL
index 88e49d5e9..39fee11ca 100644
--- a/INSTALL
+++ b/INSTALL
@@ -4,7 +4,7 @@ Requirements
 RKWard requires:
 - Several KF6-libraries and headers (>= 6.0) (https://www.kde.org)
 - Qt-libraries and headers (>= 6.6) (https://qt.io)
-- R and headers (https://www.r-project.org); at the time of this writing, version 3.4.4
+- R and headers (https://www.r-project.org); at the time of this writing, version 3.4.4 (on Windows: version 4.2.0)
   or later is required. Note, however, that old versions are not actively tested.
 - CMake (https://cmake.org)
 
diff --git a/rkward/rbackend/rkrbackend.cpp b/rkward/rbackend/rkrbackend.cpp
index 186306d4a..66f91ee83 100644
--- a/rkward/rbackend/rkrbackend.cpp
+++ b/rkward/rbackend/rkrbackend.cpp
@@ -66,6 +66,15 @@ void RK_setupGettext(const QString &locale_dir) {
 }
 
 ///// interrupting R
+static bool RK_IsRInterruptPending() {
+	// NOTE: if R_interrupts_pending stops being exported one day, we might be able to use R_CheckUserInterrupt() inside an R_ToplevelExec() to find out, whether an interrupt was still pending.
+#ifdef Q_OS_WIN
+	return ROb(UserBreak;
+#else
+	return ROb(R_interrupts_pending);
+#endif
+}
+
 void RK_scheduleIntr() {
 	RK_DEBUG(RBACKEND, DL_DEBUG, "interrupt scheduled");
 	RKRBackend::repl_status.interrupted = true;
@@ -140,11 +149,7 @@ void clearPendingInterrupt_Worker(void *) {
 
 void RKRBackend::clearPendingInterrupt() {
 	RK_TRACE(RBACKEND);
-#ifdef Q_OS_WIN
-	if (!ROb(UserBreak)) return;
-#else
-	if (!ROb(R_interrupts_pending)) return;
-#endif
+	if (!RK_IsRInterruptPending()) return;
 	RKRBackend::repl_status.interrupted = false;
 
 	bool passed = RFn::R_ToplevelExec(clearPendingInterrupt_Worker, nullptr);
@@ -246,12 +251,10 @@ int RReadConsole(const char *prompt, unsigned char *buf, int buflen, int hist) {
 					- Handling user commands is totally different from all other commands, and relies on R's "REPL" (read-evaluate-print-loop). This is a whole bunch of dedicated code, but there is no other way to achieve handling of commands as if they had been entered on a plain R console (including auto-printing, and toplevel handlers). Most importantly, since important symbols are not exported, such as R_Visible. Vice versa, it is not possible to treat all commands like user commands, esp. in substacks.
 
 					Problems to deal with:
-					- R_ReadConsole serves a lot of different functions, including reading in code, but also handling user input for readline() or browser(). This makes it necessary to carefully track the current status using "repl_status". You will find repl_status to be modified at a couple of different functions.
+					- R_ReadConsole serves a lot of different functions, including reading in code, but also handling user input for readline() or browser(). This makes it necessary to carefully track the current status using "repl_status". You will find repl_status to be modified at a couple of different functions. Sorry for the resulting spaghetti code!
 					- One difficulty lies in finding out, just when a command has finished (successfully or with an error).
 					See below (RKRBackend::repl_status.user_command_status == RKRBackend::RKReplStatus::UserCommandRunning)
-					for this, and and doError() for finding out, if an error occured.
-					NOTE; in R 2.12.0 and above, RFn::Rf_countContexts() might help to find out when we are back to square 1!
-					*/
+					for this, and and RKUserCommandErrorDetection for finding out, if an error occured. */
 					RKRBackend::repl_status.user_command_transmitted_up_to = 0;
 					RKRBackend::repl_status.user_command_completely_transmitted = false;
 					RKRBackend::repl_status.user_command_parsed_up_to = 0;
@@ -634,20 +637,13 @@ struct RKUserCommandErrorDetection {
 		if ((RKRBackend::repl_status.eval_depth == 0) && (!RKRBackend::repl_status.browser_context) && (!RKRBackend::this_pointer->isKilled()) && (RKRBackend::repl_status.user_command_status != RKRBackend::RKReplStatus::NoUserCommand)) {
 			RKRBackend::repl_status.user_command_status = RKRBackend::RKReplStatus::UserCommandFailed;
 		}
-		if (RKRBackend::repl_status.interrupted) {
-			// it is unlikely, but possible, that an interrupt signal was received, but the current command failed for some other reason, before processing was actually interrupted. In this case, R_interrupts_pending is not yet cleared.
-			// NOTE: if R_interrupts_pending stops being exported one day, we might be able to use R_CheckUserInterrupt() inside an R_ToplevelExec() to find out, whether an interrupt was still pending.
-#ifdef Q_OS_WIN
-			if (ROb(UserBreak)) {
-#else
-			if (ROb(R_interrupts_pending)) {
-#endif
-				return;
-			}
-		}
 
-		markLastWarningAsErrorMessage();
-		RK_DEBUG(RBACKEND, DL_DEBUG, "error in user command");
+		// it is unlikely, but possible, that an interrupt signal was received, but the current command failed for some other reason, before processing was actually interrupted. In this case, R_interrupts_pending is not yet cleared.
+		const bool command_was_interrupted = RKRBackend::repl_status.interrupted && !RK_IsRInterruptPending();
+		if (!command_was_interrupted) {
+			markLastWarningAsErrorMessage();
+			RK_DEBUG(RBACKEND, DL_DEBUG, "error in user command");
+		}
 	}
 };
 static RKUserCommandErrorDetection user_command_error_detect;



More information about the rkward-tracker mailing list