Dave Jarvis' Repositories

git clone https://repo.autonoma.ca/repo/keenwrite.git

Add R chunking

AuthorDaveJarvis <email>
Date2022-05-14 23:47:30 GMT-0700
Commit034e0469b112eb68f91c8278c4676718f638a425
Parent5f96d01
Delta125 lines added, 57 lines removed, 68-line increase
src/main/resources/com/keenwrite/messages.properties
Main.status.error.bootstrap.eval=Note: Bootstrap variable of ''{0}'' not found
-Main.status.error.parse={0} (near ${Main.status.text.offset} {1})
+Main.status.error.parse=Evaluation error: {0}
Main.status.error.def.blank=Move the caret to a word before inserting a variable
Main.status.error.def.empty=Create a variable before inserting one
src/main/java/com/keenwrite/ui/actions/GuiCommands.java
}
- public void file_export_markdown() {
- file_export( MARKDOWN_PLAIN );
- }
-
private void fireExportFailedEvent() {
runLater( ExportFailedEvent::fire );
src/main/java/com/keenwrite/processors/r/RChunkEvaluator.java
+/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
+package com.keenwrite.processors.r;
+
+import com.keenwrite.processors.ProcessorContext;
+
+import java.util.function.Function;
+
+import static com.keenwrite.constants.Constants.STATUS_PARSE_ERROR;
+import static com.keenwrite.events.StatusEvent.clue;
+
+/**
+ * Transforms a document containing R statements into Markdown. The statements
+ * are part of an R chunk, <code>```{r}</code>.
+ */
+public final class RChunkEvaluator implements Function<String, String> {
+
+ private final ProcessorContext mContext;
+
+ /**
+ * Constructs an evaluator capable of executing R statements.
+ *
+ * @param context Used to initialize the {@link RBootstrapController}.
+ */
+ public RChunkEvaluator( final ProcessorContext context ) {
+ mContext = context;
+ }
+
+ /**
+ * Evaluates the given R statements and returns the result as a string.
+ * If an image was produced, the calling code is responsible for persisting
+ * and making the file embeddable into the document.
+ *
+ * @param r The R statements to evaluate.
+ * @return The output from the final R statement.
+ */
+ @Override
+ public String apply( final String r ) {
+ try {
+ RBootstrapController.init( mContext );
+ return Engine.eval( r );
+ } catch( final Exception ex ) {
+ clue( STATUS_PARSE_ERROR, ex.getMessage() );
+
+ return r;
+ }
+ }
+}
src/main/java/com/keenwrite/processors/r/RInlineEvaluator.java
+/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
+package com.keenwrite.processors.r;
+
+import com.keenwrite.processors.Processor;
+import com.keenwrite.processors.ProcessorContext;
+
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+import static com.keenwrite.constants.Constants.STATUS_PARSE_ERROR;
+import static com.keenwrite.events.StatusEvent.clue;
+import static com.keenwrite.processors.IdentityProcessor.IDENTITY;
+
+/**
+ * Evaluates inline R statements.
+ */
+public final class RInlineEvaluator
+ implements Function<String, String>, Predicate<String> {
+ public static final String PREFIX = "`r#";
+ public static final String SUFFIX = "`";
+
+ private static final int PREFIX_LENGTH = PREFIX.length();
+ private static final int SUFFIX_LENGTH = SUFFIX.length();
+
+ private final Processor<String> mProcessor;
+
+ /**
+ * Constructs an evaluator capable of executing R statements.
+ */
+ public RInlineEvaluator( final ProcessorContext context ) {
+ mProcessor = new RVariableProcessor( IDENTITY, context );
+ }
+
+ /**
+ * Evaluates all R statements in the source document and inserts the
+ * calculated value into the generated document.
+ *
+ * @param text The document text that includes variables that should be
+ * replaced with values when rendered as HTML.
+ * @return The generated document with output from all R statements
+ * substituted with value returned from their execution.
+ */
+ @Override
+ public String apply( final String text ) {
+ try {
+ final var len = text.length();
+ final var r = mProcessor.apply(
+ text.substring( PREFIX_LENGTH, len - SUFFIX_LENGTH )
+ );
+
+ // Return the evaluated R expression for insertion back into the text.
+ return Engine.eval( r );
+ } catch( final Exception ex ) {
+ clue( STATUS_PARSE_ERROR, ex.getMessage() );
+
+ // If the string couldn't be parsed using R, append the statement
+ // that failed to parse, instead of its evaluated value.
+ return text;
+ }
+ }
+
+ /**
+ * Answers whether the engine associated with this evaluator may attempt to
+ * evaluate the given source code statement.
+ *
+ * @param code The source code to verify.
+ * @return {@code true} if the code may be evaluated.
+ */
+ @Override
+ public boolean test( final String code ) {
+ return code.startsWith( PREFIX );
+ }
+}
src/main/java/com/keenwrite/processors/r/RProcessor.java
-/* Copyright 2020-2021 White Magic Software, Ltd. -- All rights reserved. */
-package com.keenwrite.processors.r;
-
-import com.keenwrite.processors.ExecutorProcessor;
-import com.keenwrite.processors.Processor;
-import com.keenwrite.processors.ProcessorContext;
-
-import java.util.function.Function;
-
-import static com.keenwrite.processors.IdentityProcessor.IDENTITY;
-
-/**
- * Responsible for processing R statements within a text block.
- */
-public final class RProcessor
- extends ExecutorProcessor<String> implements Function<String, String> {
- private final Processor<String> mProcessor;
- private final InlineRProcessor mInlineRProcessor;
-
- public RProcessor( final ProcessorContext context ) {
- final var irp = new InlineRProcessor( IDENTITY, context );
- final var rvp = new RVariableProcessor( irp, context );
-
- mProcessor = new ExecutorProcessor<>( rvp );
- mInlineRProcessor = irp;
- }
-
- public String apply( final String text ) {
- if( !mInlineRProcessor.isReady() ) {
- mInlineRProcessor.init();
- }
-
- return mProcessor.apply( text );
- }
-
- /**
- * Called when the {@link InlineRProcessor} is instantiated, which triggers
- * a re-evaluation of all R expressions in the document. Without this, when
- * the document is first viewed, no R expressions are evaluated until the
- * user interacts with the document.
- */
- public void init() {
- mInlineRProcessor.init();
- }
-
- public boolean isReady() {
- return mInlineRProcessor.isReady();
- }
-}
src/main/java/com/keenwrite/processors/r/RVariableProcessor.java
package com.keenwrite.processors.r;
+import com.keenwrite.processors.Processor;
import com.keenwrite.processors.ProcessorContext;
import com.keenwrite.processors.VariableProcessor;
* <pre>v$tree$leaf</pre>.
*/
-public final class RVariableProcessor extends VariableProcessor {
+public class RVariableProcessor extends VariableProcessor {
public RVariableProcessor(
- final InlineRProcessor irp, final ProcessorContext context ) {
- super( irp, context );
+ final Processor<String> successor, final ProcessorContext context ) {
+ super( successor, context );
}