[education/rkward] rkward: Implement selection of chunks
Thomas Friedrichsmeier
null at kde.org
Mon May 26 15:06:38 BST 2025
Git commit 907570e1ca43eff0959c8a2bca10f36d5e9fc36f by Thomas Friedrichsmeier.
Committed on 26/05/2025 at 14:06.
Pushed by tfry into branch 'master'.
Implement selection of chunks
M +6 -0 rkward/autotests/rkparsedscript_test.cpp
M +32 -1 rkward/misc/rkparsedscript.cpp
M +2 -0 rkward/misc/rkparsedscript.h
M +10 -0 rkward/windows/rkcommandeditorwindow.cpp
https://invent.kde.org/education/rkward/-/commit/907570e1ca43eff0959c8a2bca10f36d5e9fc36f
diff --git a/rkward/autotests/rkparsedscript_test.cpp b/rkward/autotests/rkparsedscript_test.cpp
index 47ccb57bf..876c61775 100644
--- a/rkward/autotests/rkparsedscript_test.cpp
+++ b/rkward/autotests/rkparsedscript_test.cpp
@@ -84,6 +84,7 @@ class RKParsedScriptTest : public QObject {
while (ctx.valid())
ctx = ps.nextStatement(ctx);
ctx = ps.firstContextInStatement(ctx0); // NOTE: This one may stay at the same position
+ ctx = ps.firstContextInChunk(ctx0);
ctx = ctx0;
while (ctx.valid())
ctx = ps.nextOuter(ctx);
@@ -110,6 +111,7 @@ class RKParsedScriptTest : public QObject {
while (ctx.valid())
ctx = ps.prevStatement(ctx);
ctx = ps.lastContextInStatement(ctx0); // May stay in same position
+ ps.lastPositionInChunk(ctx0);
ctx = ctx0;
while (ctx.valid())
ctx = ps.prevOuter(ctx);
@@ -302,6 +304,10 @@ class RKParsedScriptTest : public QObject {
ctx = moveAndCheck(ps.prevStatement(ctx), u"symb11"_s);
QVERIFY(!ps.prevStatement(ctx).valid());
+ ctx = ps.contextAtPos(script.indexOf(u"symb14"));
+ ctx = moveAndCheck(ps.firstContextInChunk(ctx), u"symb11"_s);
+ QCOMPARE(script.mid(ps.lastPositionInChunk(ctx) - 6, 6), u"symb17"); // NOTE: inclusion or not of final newline is not critical
+
ctx = ps.contextAtPos(script.indexOf(u"This is markdown"));
ctx = moveAndCheck(ps.nextCodeChunk(ctx), u".some"_s);
diff --git a/rkward/misc/rkparsedscript.cpp b/rkward/misc/rkparsedscript.cpp
index 521a6f546..83f3de328 100644
--- a/rkward/misc/rkparsedscript.cpp
+++ b/rkward/misc/rkparsedscript.cpp
@@ -357,7 +357,7 @@ RKParsedScript::ContextIndex RKParsedScript::prevCodeChunk(const ContextIndex fr
if (!from.valid()) return ContextIndex();
// For general logic, see nextCodeChunk(), above. We need to reverse across two chunk starts, here
- // If we are *inside* a code chunk, we need to reverse to starts, else just one.
+ // If we are *inside* a code chunk, we need to reverse two starts, else just one.
int chunkstarts = 1;
auto parent = from;
while (parent.valid()) {
@@ -386,6 +386,37 @@ RKParsedScript::ContextIndex RKParsedScript::prevCodeChunk(const ContextIndex fr
return ContextIndex();
}
+RKParsedScript::ContextIndex RKParsedScript::firstContextInChunk(const ContextIndex from) const {
+ RK_TRACE(MISC);
+ auto parent = from;
+ while (parent.valid()) {
+ parent = parentRegion(parent);
+ if (getContext(parent).type == Top) {
+ break;
+ }
+ }
+ if (!parent.valid()) return ContextIndex();
+ int i = parent.index;
+ do {
+ ++i;
+ } while (i < context_list.size() && context_list.at(i).type == Delimiter);
+ if (i >= context_list.size()) return ContextIndex();
+ return ContextIndex(i);
+}
+
+int RKParsedScript::lastPositionInChunk(const ContextIndex from) const {
+ RK_TRACE(MISC);
+ auto ctx = from;
+ while (ctx.valid()) {
+ auto nctx = nextContext(ctx);
+ if (getContext(nctx).type == Top) {
+ break;
+ }
+ ctx = nctx;
+ }
+ return getContext(ctx).end;
+}
+
RKParsedScript::ContextIndex RKParsedScript::nextToplevel(const ContextIndex from) const {
RK_TRACE(MISC);
auto ctx = from;
diff --git a/rkward/misc/rkparsedscript.h b/rkward/misc/rkparsedscript.h
index 4d1262690..800f05bc2 100644
--- a/rkward/misc/rkparsedscript.h
+++ b/rkward/misc/rkparsedscript.h
@@ -110,6 +110,8 @@ class RKParsedScript {
/** Next code Region in R Markdown document */
ContextIndex nextCodeChunk(const ContextIndex from) const;
ContextIndex prevCodeChunk(const ContextIndex from) const;
+ ContextIndex firstContextInChunk(const ContextIndex from) const;
+ int lastPositionInChunk(const ContextIndex from) const;
/** retrieve the context at the given index. Safe to call, even with an invalid index
* (in which case the outermost context will be returned). */
diff --git a/rkward/windows/rkcommandeditorwindow.cpp b/rkward/windows/rkcommandeditorwindow.cpp
index d612db000..e161dacd1 100644
--- a/rkward/windows/rkcommandeditorwindow.cpp
+++ b/rkward/windows/rkcommandeditorwindow.cpp
@@ -196,6 +196,16 @@ class RKCodeNavigation : public QWidget {
auto posa = ps.getContext(ps.firstContextInStatement(ci)).start;
auto posb = ps.lastPositionInStatement(ci);
newpos.selection = KTextEditor::Range(positionToCursor(posa), positionToCursor(posb + 1));
+ } else if (command == u'S') {
+ if (!rmdmode) {
+ message->setText(i18n("Command 'S' is for R Markdown, only"));
+ message->show();
+ updatePos();
+ return;
+ }
+ auto posa = ps.getContext(ps.firstContextInChunk(ci)).start;
+ auto posb = ps.lastPositionInChunk(ci);
+ newpos.selection = KTextEditor::Range(positionToCursor(posa), positionToCursor(posb + 1));
} else {
RK_DEBUG(COMMANDEDITOR, DL_WARNING, "unknown navigation commmand");
message->setText(i18n("Unknown command '%1'").arg(command));
More information about the rkward-tracker
mailing list