Skip to content

Feature: Add command-driven plot(...) that renders to PNG and inserts into Word#2

Draft
Copilot wants to merge 3 commits intomasterfrom
copilot/fix-a8f95526-fa87-43cb-a967-1562029890cf
Draft

Feature: Add command-driven plot(...) that renders to PNG and inserts into Word#2
Copilot wants to merge 3 commits intomasterfrom
copilot/fix-a8f95526-fa87-43cb-a967-1562029890cf

Conversation

Copy link
Copy Markdown

Copilot AI commented Sep 26, 2025

This PR implements a new command-driven plotting feature for WordMat that allows users to create mathematical plots using simple text commands directly in Word documents.

Overview

Users can now type plot commands like:

plot(sin(x), -2π, 2π)
plot(x^2, -5, 5; title="Parabola", grid=true, width=600, height=400)
plot(cos(3*x), 0, 10; backend="gnuplot", linewidth=2)

When the user selects the text and clicks Plot Selection (or uses a keyboard shortcut), WordMat:

  1. Parses the command with strict security validation
  2. Calls an external backend (Python/Matplotlib or Gnuplot) to render a PNG
  3. Inserts the PNG as an inline image with proper scaling and alt-text

Key Features

  • Security-First Design: Expression validation uses a strict whitelist of mathematical functions (sin, cos, exp, etc.) with no arbitrary code execution
  • Dual Backend Support: Choose between Python/Matplotlib or Gnuplot for rendering
  • Rich Customization: Control titles, grid lines, dimensions, DPI, line width, and more through command options
  • Word Integration: Seamless image insertion with proper scaling and accessibility features
  • Robust Error Handling: User-friendly error messages with setup guidance for missing dependencies

Implementation

New VBA Modules

  • PlotCommandHandler.bas: Core plotting engine with parsing, validation, and backend execution
  • PlotCommandTests.bas: Comprehensive test suite with 5+ validation tests
  • PlotDemo.bas: Interactive demo with sample commands for testing

Modified VBA Modules

  • RibbonSubs.bas: Added Rib_PlotSelection ribbon callback
  • ModuleSettings.bas: Added PlotSelection to keyboard shortcut enum
  • ModuleKeyboardShortcuts.bas: Added keyboard shortcut handling

Documentation

  • PLOT_FEATURE_README.md: Complete feature documentation with examples
  • README.md: Updated with plot feature overview

Usage

  1. Type a plot command in your Word document
  2. Select the command text
  3. Click WordMat → Plot Selection or use keyboard shortcut
  4. The plot is generated and inserted as an image

Testing

The implementation includes comprehensive tests:

RunPlotTests           ' Run full test suite
CreatePlotDemoDocument ' Create document with examples
QuickPlotTest         ' Test basic functionality

Dependencies

  • Matplotlib backend: Requires Python with matplotlib and numpy packages
  • Gnuplot backend: Requires gnuplot executable in system PATH

Both backends are optional - users can choose their preferred one based on their setup.

Motivation

This feature addresses the need for:

  • Reproducible plots: The plot command text becomes the source of truth
  • Faster workflow: No need to switch between applications for simple mathematical plots
  • Command-driven experience: Appeals to users who prefer text commands over GUI dialogs
  • Academic/scientific documents: Perfect for assignments and reports requiring mathematical visualizations

Resolves #[issue-number] by providing the requested command-driven plotting workflow with both Matplotlib and Gnuplot backend support.

Original prompt

This section details on the original issue you should resolve

<issue_title>Feature: Add command-driven plot(...) that renders to PNG and inserts into Word</issue_title>
<issue_description>Add a text-based plotting workflow to WordMat so users can type commands like:
plot(sin(x), -2π, 2π)
plot(x^2, -5, 5; title="Parabola", grid=true, width=600, height=400, dpi=150)
plot(sin(x), -10, 10; backend="gnuplot")

When the user runs WordMat → Plot selection (or a keyboard shortcut), WordMat:

Parses the selected text for a plot(...) command.

Calls an external backend (Python/Matplotlib or Gnuplot) to render a PNG.

Inserts the PNG at the cursor (inline image) with optional caption/alt text.

This provides a command-driven experience (like MATLAB/Octave/Python) while keeping deliverables inside Word.

Motivation

Current plotting is GUI-driven (dialogs/GeoGebra). Some users prefer commands over UI.

Reproducibility: the plot(...) text in the doc becomes a source of truth you can re-plot at any time.

Faster iteration for assignments and reports that require many simple function plots.

User stories

As a student, I want to type plot(sin(x), -2π, 2π) and get a clean plot in my document without leaving Word.

As a power user, I want to choose Matplotlib or Gnuplot as the rendering backend and control size/DPI/grid/title via keywords.

As a grader/teacher, I want to re-generate plots from the original plot(...) commands embedded in the doc for verification.

Non-goals (v1)

No 3D plots in v1.

No multi-axis or subplots (one axes per command).

No inline live previews; only generated PNGs.

Not parsing arbitrary OMath/Equation objects (v1 expects plain text selection).

UX / UI

Ribbon: Add Plot selection button under WordMat → Graphs (or new Commands group).

Keyboard shortcut: Alt+W, P (or configurable).

Options dialog (new “Plotting” tab):

Backend: Matplotlib (Python) | Gnuplot

Backend path(s): Python executable path, Gnuplot executable path

Defaults: width (px), height (px), dpi, grid on/off, line width

Timeout (seconds)

Keep temp images (debug) on/off

Context menu: (optional) “Plot selection with WordMat”.

Command syntax (v1)
EBNF (minimal)
plot = "plot" "(" expr "," xmin "," xmax [ ";" options ] ")"
expr = function of x using allowed tokens (see whitelist)
xmin = number | constant | expression using pi
xmax = number | constant | expression using pi
options = option { "," option }
option = key "=" value
key = "title" | "grid" | "width" | "height" | "dpi" | "backend" | "linewidth"
value = string | number | boolean

Examples
plot(sin(x), -2π, 2π)
plot(x^2 + 2x + 1, -10, 10; title="Quadratic", grid=true, dpi=200)
plot(sin(x)/x, -20, 20; linewidth=2)
plot(cos(3
x), 0, 10; backend="gnuplot", width=800, height=400)

Allowed functions/tokens (v1)

Constants: pi (and π), e

Functions: sin, cos, tan, asin, acos, atan, exp, log, ln, sqrt, abs

Operators: + - * / ^

Parentheses and whitespace

Security: No raw eval on user input. Map tokens to a whitelist of math functions and parse safely.

High-level design
Flow

Get selection: If selection text matches plot(…), proceed; else show a helpful error.

Parse: Use a small hand-rolled parser or a simple tokenizer to extract expr, xmin, xmax, options.

Normalize: Replace π with pi, ^ with ** (for Python), etc.

Backend dispatch:

If backend option set, honor it; otherwise use global default from Options.

Render:

Call external process (Python or Gnuplot) with a generated script and a temp output PNG path.

Insert:

Use Word COM: InlineShapes.AddPicture(tempPng, LinkToFile: false, SaveWithDocument: true).

Optionally set width/height in points to match pixels at 96 DPI, or scale proportionally.

Cleanup: Delete temp script (unless “Keep temp” is enabled).

Project structure (suggested)

Plotting/PlotCommandHandler.cs — entry point from Ribbon/shortcut

Plotting/Parser/PlotParser.cs — tokenizer + AST + options

Plotting/Backends/IPlotBackend.cs — interface

Plotting/Backends/MatplotlibBackend.cs

Plotting/Backends/GnuplotBackend.cs

Plotting/Word/WordInserter.cs — image insertion utilities

Options/PlotOptionsPage.cs — options UI

Word integration details (C# / VSTO)
// Pseudocode
void PlotSelection()
{
var sel = Globals.ThisAddIn.Application.Selection;
string text = sel?.Range?.Text?.Trim() ?? string.Empty;

if (!PlotParser.LooksLikePlotCommand(text))
{
    ShowError("Select a plot(...) command, e.g. plot(sin(x), -2π, 2π).");
    return;
}

var cmd = PlotParser.Parse(text); // throws ParseException with good messages
var backend = BackendFactory.Resolve(cmd.Options.Backend ?? Options.DefaultBackend);

string tempPng = Path.Combine(Path.GetTempPath(), $"wordmat_plot_{Guid.NewGuid()}.png");
backend.Render(cmd, tempPng, Options);

// Insert inline and scale
var range = sel.Range;
var shape = range.InlineShapes.AddPicture(tempPng, LinkToFile: false, SaveWithD...
Fixes #1

💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

Copilot AI and others added 2 commits September 26, 2025 17:32
…uplot backends

Co-authored-by: JohnnyTheCoder1 <111908128+JohnnyTheCoder1@users.noreply.github.com>
…ocumentation

Co-authored-by: JohnnyTheCoder1 <111908128+JohnnyTheCoder1@users.noreply.github.com>
Copilot AI changed the title [WIP] Feature: Add command-driven plot(...) that renders to PNG and inserts into Word Feature: Add command-driven plot(...) that renders to PNG and inserts into Word Sep 26, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: Add command-driven plot(...) that renders to PNG and inserts into Word

2 participants