Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
dc69dd7
feat(builder): add first experiment
MaxAtoms Jun 24, 2025
fbafaab
feat(builder): add engine and query support
MaxAtoms Jun 24, 2025
9a6abdc
feat(builder): fixes from review
MaxAtoms Jun 24, 2025
7949d5d
feat(plugin): add FlowrAnalyzerPlugin and DESCRIPTION-file plugin
stimjannik Jul 2, 2025
7953f9a
test(plugin): library versions from DESCRIPTION test
stimjannik Jul 2, 2025
16762a9
feat(plugin): add (un)registering plugins in FlowrAnalyzerBuilder
stimjannik Jul 2, 2025
ad9d962
feat(builder): simplifications
MaxAtoms Jul 16, 2025
13841b5
feat(builder): use EngineConfig type
MaxAtoms Jul 16, 2025
17ac956
feat(builder): use varargs/rest parameter syntax
MaxAtoms Jul 17, 2025
7ea5a31
refactor(plugin): use abstract classes instead of interfaces only
stimjannik Jul 17, 2025
4d097e6
lint-fix(plugin): fixed linter issues
stimjannik Jul 17, 2025
54f6612
lint-fix(plugin): fixed linter issues
stimjannik Jul 17, 2025
39e7ba7
feat(plugin): add new DESCRIPTION parser
stimjannik Jul 22, 2025
62e50ae
feat(plugin): add loading order from DESCRIPTION retriever
stimjannik Jul 22, 2025
809670c
test-fix(plugin): adjust description file test
stimjannik Jul 22, 2025
6995247
lint(plugin): adjust analyzer and pluginConfig to be ignored
stimjannik Jul 22, 2025
cfff464
lint-fix(plugin): fix mixed spaces and tabs
stimjannik Jul 22, 2025
0c867b7
lint-fix(plugin): unify use of `:` for type annotations
stimjannik Jul 24, 2025
2bdc456
refactor(plugin/files): move dcf-parsing to file
stimjannik Jul 31, 2025
3df5299
feat(plugin): derive package version from multiple constraints
stimjannik Jul 31, 2025
cb935b1
wip(plugin): add libraries to dependency query
stimjannik Aug 6, 2025
96982a1
lint-fix(plugin): add missing semicolon
stimjannik Aug 7, 2025
dcb24ee
feat(plugin): add description file infos to dependency query
stimjannik Aug 7, 2025
76fd1c5
feat-fix(plugin): namespace returns undefined for constraints if no pkg
stimjannik Aug 7, 2025
12df850
test(dependencies-query): add tests for packages with versions
stimjannik Aug 7, 2025
6ae00e7
lint-fix(dependencies-query): fix braces
stimjannik Aug 7, 2025
e26fe2d
feat(builder): add cfg and force param
MaxAtoms Aug 15, 2025
f8f1462
feat(builder): add reset function
MaxAtoms Aug 15, 2025
57a57fa
feat(analyzer): use analyzer in repl
MaxAtoms Aug 19, 2025
6a6c498
lint-fix: type-annotation spacing
MaxAtoms Aug 19, 2025
9066eb5
feat-fix: re-introduce timing info to repl
MaxAtoms Aug 21, 2025
30dc30c
feat: use analyzer in repl query
MaxAtoms Aug 22, 2025
4fc137e
feat: expose argument parser per command
MaxAtoms Aug 23, 2025
c955f10
feat: pass analyzer to repl-query
MaxAtoms Aug 23, 2025
034a925
feat: add parse pipeline to analyzer
MaxAtoms Aug 23, 2025
1a100ea
feat: introduce simpleCfg to analyzer
MaxAtoms Aug 27, 2025
1f5b9cb
feat: use analyzer for server
MaxAtoms Aug 28, 2025
2ddc051
feat: use analyzer for search, query, and linter
MaxAtoms Sep 1, 2025
bc4bc92
feat: use analyzer to get cfg in queries
MaxAtoms Sep 1, 2025
f453309
feat-fix: prevent excessive R-Shell creation
MaxAtoms Sep 1, 2025
4268332
Merge remote-tracking branch 'origin/main' into 1512-builder-api
MaxAtoms Sep 2, 2025
296cfdd
feat-fix: set correct slicing params
MaxAtoms Sep 4, 2025
8298aff
feat-fix: clean-up
MaxAtoms Sep 4, 2025
c9da2a8
Merge remote-tracking branch 'origin/main' into 1512-builder-api
MaxAtoms Sep 4, 2025
4f89042
feat-fix(analyzer): cfg caching
MaxAtoms Sep 4, 2025
b75dd86
doc(analyzer): clean-up
MaxAtoms Sep 5, 2025
fef77d8
feat(config): allow config amendment without return
MaxAtoms Sep 5, 2025
9a32ace
doc(repl): improve comments
MaxAtoms Sep 5, 2025
5fd85f5
feat-fix(query): resolve promise
MaxAtoms Sep 8, 2025
0939abf
feat(analyzer): use analyzer for queries
MaxAtoms Sep 8, 2025
298c658
feat-fix: use more specific type
MaxAtoms Sep 8, 2025
4800666
feat-fix(libraries): include libraries in new dependencies query
stimjannik Sep 10, 2025
e203f75
feat(analyzer): add documentation comments
MaxAtoms Sep 12, 2025
72c1269
feat-fix(analyzer): rename ArrayMap
MaxAtoms Sep 12, 2025
b20adc4
feat-fix(repl): fix config updates
MaxAtoms Sep 12, 2025
04e92cb
feat-fix(analyzer): proposal to generalize analyzer over parser
MaxAtoms Sep 12, 2025
118be52
feat-fix(libraries): versions for ':::' and '::' reduced to necessary
stimjannik Sep 23, 2025
af6ec54
test-fix(libraries): replace old values in expected results
stimjannik Sep 23, 2025
a1f519f
feat-fix(server): use then syntax
MaxAtoms Sep 24, 2025
b890d70
feat-fix(dataframe): map nodes
MaxAtoms Sep 24, 2025
7534602
Merge branch 'main' into 1512-builder-api
EagleoutIce Sep 25, 2025
763f679
refactor: recover buildability
EagleoutIce Sep 25, 2025
051f659
refactor: output tunes to existing tests
EagleoutIce Sep 25, 2025
44e50cc
refactor: minor patches to asyncness
EagleoutIce Sep 25, 2025
d69e1c2
refactor: design of separate cache api
EagleoutIce Sep 25, 2025
aea3a79
feat: flo's opinionated analyzer caching updates
EagleoutIce Sep 25, 2025
83fa01d
refactor: simplification iteration
EagleoutIce Sep 25, 2025
9eb1694
refactor: defer early force in query print
EagleoutIce Sep 25, 2025
034b134
refactor: query improvements for projects
EagleoutIce Sep 25, 2025
c413dcb
feat-fix: data naming
EagleoutIce Sep 25, 2025
2bf0d09
lint-fix: handle linter awaits
EagleoutIce Sep 25, 2025
038d1a3
refactor: remove only debug fixture
EagleoutIce Sep 25, 2025
b6d7a0b
Add analyzer to Wiki (#1940)
MaxAtoms Sep 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 3 additions & 31 deletions src/cli/flowr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,23 @@ import { NetServer, WebSocketServerWrapper } from './repl/server/net';
import { flowrVersion } from '../util/version';
import commandLineUsage from 'command-line-usage';
import { log, LogLevel } from '../util/log';
import { bold, ColorEffect, Colors, FontStyles, formatter, italic, setFormatter, voidFormatter } from '../util/text/ansi';
import { FontStyles, formatter, italic, setFormatter, voidFormatter } from '../util/text/ansi';
import commandLineArgs from 'command-line-args';
import type { EngineConfig, FlowrConfigOptions, KnownEngines } from '../config';
import { amendConfig, getConfig, getEngineConfig, parseConfig } from '../config';
import { amendConfig, getConfig, parseConfig } from '../config';
import { guard } from '../util/assert';
import type { ScriptInformation } from './common/scripts-info';
import { scripts } from './common/scripts-info';
import { RShell, RShellReviveOptions } from '../r-bridge/shell';
import { waitOnScript } from './repl/execute';
import { standardReplOutput } from './repl/commands/repl-main';
import { repl, replProcessAnswer } from './repl/core';
import { printVersionInformation } from './repl/commands/repl-version';
import { printVersionRepl } from './repl/print-version';
import { defaultConfigFile, flowrMainOptionDefinitions, getScriptsText } from './flowr-main-options';
import { TreeSitterExecutor } from '../r-bridge/lang-4.x/tree-sitter/tree-sitter-executor';
import type { KnownParser } from '../r-bridge/parser';
import fs from 'fs';
import path from 'path';
import { retrieveEngineInstances } from '../engines';

export const toolName = 'flowr';

Expand Down Expand Up @@ -137,33 +136,6 @@ function createConfig(): FlowrConfigOptions {
return config;
}


async function retrieveEngineInstances(config: FlowrConfigOptions): Promise<{ engines: KnownEngines, default: keyof KnownEngines }> {
const engines: KnownEngines = {};
if(getEngineConfig(config, 'r-shell')) {
// we keep an active shell session to allow other parse investigations :)
engines['r-shell'] = new RShell(getEngineConfig(config, 'r-shell'), {
revive: RShellReviveOptions.Always,
onRevive: (code, signal) => {
const signalText = signal == null ? '' : ` and signal ${signal}`;
console.log(formatter.format(`R process exited with code ${code}${signalText}. Restarting...`, { color: Colors.Magenta, effect: ColorEffect.Foreground }));
console.log(italic(`If you want to exit, press either Ctrl+C twice, or enter ${bold(':quit')}`));
}
});
}
if(getEngineConfig(config, 'tree-sitter')) {
await TreeSitterExecutor.initTreeSitter(getEngineConfig(config, 'tree-sitter'));
engines['tree-sitter'] = new TreeSitterExecutor();
}
let defaultEngine = config.defaultEngine;
if(!defaultEngine || !engines[defaultEngine]) {
// if a default engine isn't specified, we just take the first one we have
defaultEngine = Object.keys(engines)[0] as keyof KnownEngines;
}
log.info(`Using engines ${Object.keys(engines).join(', ')} with default ${defaultEngine}`);
return { engines, default: defaultEngine };
}

function hookSignalHandlers(engines: { engines: KnownEngines; default: keyof KnownEngines }) {
const end = () => {
if(options.execute === undefined) {
Expand Down
61 changes: 28 additions & 33 deletions src/cli/repl/commands/repl-cfg.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,22 @@
import type { ReplCommand, ReplOutput } from './repl-main';
import { extractCfg } from '../../../control-flow/extract-cfg';
import { createDataflowPipeline } from '../../../core/steps/pipeline/default-pipelines';
import { fileProtocol, requestFromInput } from '../../../r-bridge/retriever';
import type { ReplCodeCommand, ReplOutput } from './repl-main';
import { fileProtocol } from '../../../r-bridge/retriever';
import { cfgToMermaid, cfgToMermaidUrl } from '../../../util/mermaid/cfg';
import type { KnownParser } from '../../../r-bridge/parser';
import { ColorEffect, Colors, FontStyles } from '../../../util/text/ansi';
import type { ControlFlowInformation } from '../../../control-flow/control-flow-graph';
import type { NormalizedAst } from '../../../r-bridge/lang-4.x/ast/model/processing/decorate';
import type { CfgSimplificationPassName } from '../../../control-flow/cfg-simplification';
import { DefaultCfgSimplificationOrder } from '../../../control-flow/cfg-simplification';
import type { FlowrConfigOptions } from '../../../config';

async function controlflow(parser: KnownParser, remainingLine: string, config: FlowrConfigOptions) {
return await createDataflowPipeline(parser, {
request: requestFromInput(remainingLine.trim())
}, config).allRemainingSteps();
}

function handleString(code: string): string {
return code.startsWith('"') ? JSON.parse(code) as string : code;
}
import type { FlowrAnalysisProvider } from '../../../project/flowr-analyzer';
import { handleString } from '../core';

function formatInfo(out: ReplOutput, type: string): string {
return out.formatter.format(`Copied ${type} to clipboard.`, { color: Colors.White, effect: ColorEffect.Foreground, style: FontStyles.Italic });
}

async function produceAndPrintCfg(shell: KnownParser, remainingLine: string, output: ReplOutput, simplifications: readonly CfgSimplificationPassName[], cfgConverter: (cfg: ControlFlowInformation, ast: NormalizedAst) => string, config: FlowrConfigOptions) {
const result = await controlflow(shell, handleString(remainingLine), config);

const cfg = extractCfg(result.normalize, config, result.dataflow.graph, [...DefaultCfgSimplificationOrder, ...simplifications]);
const mermaid = cfgConverter(cfg, result.normalize);
async function produceAndPrintCfg(analyzer: FlowrAnalysisProvider, output: ReplOutput, simplifications: readonly CfgSimplificationPassName[], cfgConverter: (cfg: ControlFlowInformation, ast: NormalizedAst) => string) {
const cfg = await analyzer.controlflow([...DefaultCfgSimplificationOrder, ...simplifications]);
const normalizedAst = await analyzer.normalize();
const mermaid = cfgConverter(cfg, normalizedAst);
output.stdout(mermaid);
try {
const clipboard = await import('clipboardy');
Expand All @@ -39,45 +26,53 @@ async function produceAndPrintCfg(shell: KnownParser, remainingLine: string, out
}
}

export const controlflowCommand: ReplCommand = {
export const controlflowCommand: ReplCodeCommand = {
description: `Get mermaid code for the control-flow graph of R code, start with '${fileProtocol}' to indicate a file`,
usesAnalyzer: true,
usageExample: ':controlflow',
aliases: [ 'cfg', 'cf' ],
script: false,
fn: async({ output, parser, remainingLine, config }) => {
await produceAndPrintCfg(parser, remainingLine, output, [], cfgToMermaid, config);
argsParser: (args: string) => handleString(args),
fn: async({ output, analyzer }) => {
await produceAndPrintCfg(analyzer, output, [], cfgToMermaid);
}
};


export const controlflowStarCommand: ReplCommand = {
export const controlflowStarCommand: ReplCodeCommand = {
description: 'Returns the URL to mermaid.live',
usesAnalyzer: true,
usageExample: ':controlflow*',
aliases: [ 'cfg*', 'cf*' ],
script: false,
fn: async({ output, parser, remainingLine, config }) => {
await produceAndPrintCfg(parser, remainingLine, output, [], cfgToMermaidUrl, config);
argsParser: (args: string) => handleString(args),
fn: async({ output, analyzer }) => {
await produceAndPrintCfg(analyzer, output, [], cfgToMermaidUrl);
}
};


export const controlflowBbCommand: ReplCommand = {
export const controlflowBbCommand: ReplCodeCommand = {
description: `Get mermaid code for the control-flow graph with basic blocks, start with '${fileProtocol}' to indicate a file`,
usesAnalyzer: true,
usageExample: ':controlflowbb',
aliases: [ 'cfgb', 'cfb' ],
script: false,
fn: async({ output, parser, remainingLine, config }) => {
await produceAndPrintCfg(parser, remainingLine, output, ['to-basic-blocks'], cfgToMermaid, config);
argsParser: (args: string) => handleString(args),
fn: async({ output, analyzer }) => {
await produceAndPrintCfg(analyzer, output, ['to-basic-blocks'], cfgToMermaid);
}
};


export const controlflowBbStarCommand: ReplCommand = {
export const controlflowBbStarCommand: ReplCodeCommand = {
description: 'Returns the URL to mermaid.live',
usesAnalyzer: true,
usageExample: ':controlflowbb*',
aliases: [ 'cfgb*', 'cfb*' ],
script: false,
fn: async({ output, parser, remainingLine, config }) => {
await produceAndPrintCfg(parser, remainingLine, output, ['to-basic-blocks' ], cfgToMermaidUrl, config);
argsParser: (args: string) => handleString(args),
fn: async({ output, analyzer }) => {
await produceAndPrintCfg(analyzer, output, ['to-basic-blocks' ], cfgToMermaidUrl);
}
};
10 changes: 6 additions & 4 deletions src/cli/repl/commands/repl-commands.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { quitCommand } from './repl-quit';
import { stdioCaptureProcessor, waitOnScript } from '../execute';
import type { ReplCommand } from './repl-main';
import type { ReplBaseCommand, ReplCodeCommand, ReplCommand } from './repl-main';
import { rawPrompt } from '../prompt';
import { versionCommand } from './repl-version';
import { parseCommand } from './repl-parse';
Expand All @@ -21,7 +21,7 @@ import { scripts } from '../../common/scripts-info';
import { lineageCommand } from './repl-lineage';
import { queryCommand, queryStarCommand } from './repl-query';

function printHelpForScript(script: [string, ReplCommand], f: OutputFormatter, starredVersion?: ReplCommand): string {
function printHelpForScript(script: [string, ReplBaseCommand], f: OutputFormatter, starredVersion?: ReplBaseCommand): string {
let base = ` ${bold(padCmd(':' + script[0] + (starredVersion ? '[*]' : '')), f)}${script[1].description}`;
if(starredVersion) {
base += ` (star: ${starredVersion.description})`;
Expand Down Expand Up @@ -49,6 +49,7 @@ function printCommandHelp(formatter: OutputFormatter) {

export const helpCommand: ReplCommand = {
description: 'Show help information',
usesAnalyzer: false,
script: false,
usageExample: ':help',
aliases: [ 'h', '?' ],
Expand Down Expand Up @@ -79,7 +80,7 @@ You can combine commands by separating them with a semicolon ${bold(';',output.f
/**
* All commands that should be available in the REPL.
*/
const _commands: Record<string, ReplCommand> = {
const _commands: Record<string, ReplCommand | ReplCodeCommand> = {
'help': helpCommand,
'quit': quitCommand,
'version': versionCommand,
Expand Down Expand Up @@ -122,6 +123,7 @@ export function getReplCommands() {
aliases: [],
script: true,
usageExample: `:${script} --help`,
usesAnalyzer: false,
fn: async({ output, remainingLine }) => {
// check if the target *module* exists in the current directory, else try two dirs up, otherwise, fail with a message
let path = `${__dirname}/${target}`;
Expand Down Expand Up @@ -177,7 +179,7 @@ function initCommandMapping() {
* Get the command for a given command name or alias.
* @param command - The name of the command (without the leading `:`)
*/
export function getCommand(command: string): ReplCommand | undefined {
export function getCommand(command: string): ReplCodeCommand | ReplCommand | undefined {
if(commandMapping === undefined) {
initCommandMapping();
}
Expand Down
75 changes: 35 additions & 40 deletions src/cli/repl/commands/repl-dataflow.ts
Original file line number Diff line number Diff line change
@@ -1,93 +1,88 @@
import type { ReplCommand, ReplOutput } from './repl-main';
import { createDataflowPipeline } from '../../../core/steps/pipeline/default-pipelines';
import { fileProtocol, requestFromInput } from '../../../r-bridge/retriever';
import type { ReplCodeCommand, ReplOutput } from './repl-main';
import { fileProtocol } from '../../../r-bridge/retriever';
import { graphToMermaid, graphToMermaidUrl } from '../../../util/mermaid/dfg';
import type { KnownParser } from '../../../r-bridge/parser';
import { ColorEffect, Colors, FontStyles } from '../../../util/text/ansi';
import type { FlowrConfigOptions } from '../../../config';
import type { PipelinePerStepMetaInformation } from '../../../core/steps/pipeline/pipeline';
import { handleString } from '../core';

/**
* Obtain the dataflow graph using a known parser (such as the {@link RShell} or {@link TreeSitterExecutor}).
*/
async function replGetDataflow(config: FlowrConfigOptions, parser: KnownParser, code: string) {
return await createDataflowPipeline(parser, {
request: requestFromInput(code.trim())
}, config).allRemainingSteps();
function formatInfo(out: ReplOutput, type: string, meta: PipelinePerStepMetaInformation ): string {
return out.formatter.format(`Copied ${type} to clipboard (dataflow: ${meta['.meta'].timing + 'ms'}).`,
{ color: Colors.White, effect: ColorEffect.Foreground, style: FontStyles.Italic });
}

function handleString(code: string): string {
return code.startsWith('"') ? JSON.parse(code) as string : code;
}

function formatInfo(out: ReplOutput, type: string, timing: number): string {
return out.formatter.format(`Copied ${type} to clipboard (dataflow: ${timing}ms).`, { color: Colors.White, effect: ColorEffect.Foreground, style: FontStyles.Italic });
}

export const dataflowCommand: ReplCommand = {
export const dataflowCommand: ReplCodeCommand = {
description: `Get mermaid code for the dataflow graph, start with '${fileProtocol}' to indicate a file`,
usesAnalyzer: true,
usageExample: ':dataflow',
aliases: [ 'd', 'df' ],
script: false,
fn: async({ output, parser, remainingLine, config }) => {
const result = await replGetDataflow(config, parser, handleString(remainingLine));
const mermaid = graphToMermaid({ graph: result.dataflow.graph, includeEnvironments: false }).string;
argsParser: (args: string) => handleString(args),
fn: async({ output, analyzer }) => {
const result = await analyzer.dataflow();
const mermaid = graphToMermaid({ graph: result.graph, includeEnvironments: false }).string;
output.stdout(mermaid);
try {
const clipboard = await import('clipboardy');
clipboard.default.writeSync(mermaid);
output.stdout(formatInfo(output, 'mermaid code', result.dataflow['.meta'].timing));
output.stdout(formatInfo(output, 'mermaid code', result));
} catch{ /* do nothing this is a service thing */ }
}
};

export const dataflowStarCommand: ReplCommand = {
export const dataflowStarCommand: ReplCodeCommand = {
description: 'Returns the URL to mermaid.live',
usesAnalyzer: true,
usageExample: ':dataflow*',
aliases: [ 'd*', 'df*' ],
script: false,
fn: async({ output, parser, remainingLine, config }) => {
const result = await replGetDataflow(config, parser, handleString(remainingLine));
const mermaid = graphToMermaidUrl(result.dataflow.graph, false);
argsParser: (args: string) => handleString(args),
fn: async({ output, analyzer }) => {
const result = await analyzer.dataflow();
const mermaid = graphToMermaidUrl(result.graph, false);
output.stdout(mermaid);
try {
const clipboard = await import('clipboardy');
clipboard.default.writeSync(mermaid);
output.stdout(formatInfo(output, 'mermaid url', result.dataflow['.meta'].timing));
output.stdout(formatInfo(output, 'mermaid url', result));
} catch{ /* do nothing this is a service thing */ }
}
};


export const dataflowSimplifiedCommand: ReplCommand = {
export const dataflowSimplifiedCommand: ReplCodeCommand = {
description: `Get mermaid code for the simplified dataflow graph, start with '${fileProtocol}' to indicate a file`,
usesAnalyzer: true,
usageExample: ':dataflowsimple',
aliases: [ 'ds', 'dfs' ],
script: false,
fn: async({ output, parser, remainingLine, config }) => {
const result = await replGetDataflow(config, parser, handleString(remainingLine));
const mermaid = graphToMermaid({ graph: result.dataflow.graph, includeEnvironments: false, simplified: true }).string;
argsParser: (args: string) => handleString(args),
fn: async({ output, analyzer }) => {
const result = await analyzer.dataflow();
const mermaid = graphToMermaid({ graph: result.graph, includeEnvironments: false, simplified: true }).string;
output.stdout(mermaid);
try {
const clipboard = await import('clipboardy');
clipboard.default.writeSync(mermaid);
output.stdout(formatInfo(output, 'mermaid code', result.dataflow['.meta'].timing));
output.stdout(formatInfo(output, 'mermaid code', result));
} catch{ /* do nothing this is a service thing */ }
}
};

export const dataflowSimpleStarCommand: ReplCommand = {
export const dataflowSimpleStarCommand: ReplCodeCommand = {
description: 'Returns the URL to mermaid.live',
usesAnalyzer: true,
usageExample: ':dataflowsimple*',
aliases: [ 'ds*', 'dfs*' ],
script: false,
fn: async({ output, parser, remainingLine, config }) => {
const result = await replGetDataflow(config, parser, handleString(remainingLine));
const mermaid = graphToMermaidUrl(result.dataflow.graph, false, undefined, true);
argsParser: (args: string) => handleString(args),
fn: async({ output, analyzer }) => {
const result = await analyzer.dataflow();
const mermaid = graphToMermaidUrl(result.graph, false, undefined, true);
output.stdout(mermaid);
try {
const clipboard = await import('clipboardy');
clipboard.default.writeSync(mermaid);
output.stdout(formatInfo(output, 'mermaid url', result.dataflow['.meta'].timing));
output.stdout(formatInfo(output, 'mermaid url', result));
} catch{ /* do nothing this is a service thing */ }
}
};
1 change: 1 addition & 0 deletions src/cli/repl/commands/repl-execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ async function executeRShellCommand(output: ReplOutput, shell: RShell, statement

export const executeCommand: ReplCommand = {
description: 'Execute the given code as R code (essentially similar to using now command). This requires the `--r-session-access` flag to be set and requires the r-shell engine.',
usesAnalyzer: false,
usageExample: ':execute',
aliases: [ 'e', 'r' ],
script: false,
Expand Down
1 change: 1 addition & 0 deletions src/cli/repl/commands/repl-lineage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export function getLineage(criterion: SingleSlicingCriterion, graph: DataflowGra

export const lineageCommand: ReplCommand = {
description: 'Get the lineage of an R object',
usesAnalyzer: false,
usageExample: ':lineage',
aliases: ['lin'],
script: false,
Expand Down
Loading