Skip to content

make install_font() own function for clarity, add unit tests, work on Windows, macOS and Linux#1

Open
scivision wants to merge 8 commits intomarkagold1:masterfrom
scivision:master
Open

make install_font() own function for clarity, add unit tests, work on Windows, macOS and Linux#1
scivision wants to merge 8 commits intomarkagold1:masterfrom
scivision:master

Conversation

@scivision
Copy link
Copy Markdown

  • install_font() own function for clarity and security - didn't want to auto-run system() command deep inside a plotting function
  • add unit tests for Matlab that are deeper than visual check
  • make work on Octave and Matlab on Linux, macOS, Windows

The buildfile.m is optional, uniform way to handle install, check and test.

I realize this is a lot of changes, but most are emphasizing the automated tests. The important feature is that your functions work across Octave and Matlab on macOS, Windows, and Linux now--the tests help validate this claim in automated fashion!

Copilot AI review requested due to automatic review settings March 29, 2026 22:58
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors font installation into a dedicated install_font() helper, expands automated MATLAB unit tests for dark/undark/hand, and adds GitHub Actions CI to validate behavior across OSes.

Changes:

  • Extract font installation/verification into install_font.m and update hand.m to check/register fonts more explicitly.
  • Add MATLAB matlab.unittest test classes for dark, undark, and hand, plus minor script/test tweaks for Octave/MATLAB compatibility.
  • Add buildfile.m and a new GitHub Actions workflow to run code checks, font install, and unit tests.

Reviewed changes

Copilot reviewed 11 out of 12 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
hand.m Adds fallback parameter and new font-check logic; refactors primitive styling logic.
install_font.m New cross-platform font install helper (Windows/macOS/Linux) plus restart guidance.
dark.m Refactors styling dispatch for MATLAB/Octave graphics objects.
undark.m Suppresses global-variable analyzer warnings.
test/TestHand.m Adds MATLAB unit tests for hand() styling and font behavior.
test/TestDark.m Adds MATLAB unit tests for dark() styling across plot types.
test/TestUndark.m Adds MATLAB unit tests for undark() restoration behavior.
test_hand.m Uses 1j instead of i in a complex exponential example.
buildfile.m Adds MATLAB buildtool plan and tasks (check/test/install).
.github/workflows/ci.yml Adds CI workflow to run buildtool tasks on multiple OS/MATLAB versions.
README.md Updates platform/version claims and documents buildtool usage; adds font install notes.
.gitignore Ignores MATLAB .asv autosave files.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +103 to +107
switch class(h(kk))
case 'matlab.graphics.chart.primitive.Line'
set(h(kk),'Color',colors(index,:))
set(h(kk),'MarkerFaceColor',colors(index,:))
set(h(kk),'MarkerEdgeColor',colors(index,:))
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replacing isa(...) with switch class(...) means subclasses of these graphics primitives will no longer be styled. If you still want to cover derived chart objects, use isa checks instead of exact class matches.

Copilot uses AI. Check for mistakes.
ok = ~system(cmd);
elseif ismac()
disp('Install XKCD Script with Font Book')
ok = ~system(sprintf('open -a "Font Book" %s', xkcd_ttf));
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The macOS install command does not quote the font path. If xkcd_ttf contains spaces, open -a "Font Book" ... will fail. Wrap the path in quotes and escape as needed when building the command string.

Suggested change
ok = ~system(sprintf('open -a "Font Book" %s', xkcd_ttf));
ok = ~system(sprintf('open -a "Font Book" "%s"', xkcd_ttf));

Copilot uses AI. Check for mistakes.
estr = sprintf('%s See help graphics_toolkit for more information.\n', estr);
error('%s', estr)
else
estr = sprintf('%s Restart GNU OCtave to refresh font list.\n', estr);
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a typo in the restart message: "GNU OCtave" should be "GNU Octave".

Suggested change
estr = sprintf('%s Restart GNU OCtave to refresh font list.\n', estr);
estr = sprintf('%s Restart GNU Octave to refresh font list.\n', estr);

Copilot uses AI. Check for mistakes.
hand()

ax = gca;
if getenv('CI') == "true"
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if getenv('CI') == "true" will fail because getenv returns a char vector in MATLAB; == with a string scalar is not a valid comparison here. Use strcmp(getenv('CI'), 'true') (or convert with string(getenv('CI')) == "true").

Suggested change
if getenv('CI') == "true"
if strcmp(getenv('CI'), 'true')

Copilot uses AI. Check for mistakes.

HAND renders a plot in a theme that emulates a hand-drawn plot in an engineering notebook. It works the same way as DARK, simply run the command "hand" on your current plot to render it in a hand-drawn thme. Once converted you may continue to modify properties, zoom, and pan as desired.
HAND renders a plot in a theme that emulates a hand-drawn plot in an engineering notebook.
It works the same way as DARK, simply run the command "hand" on your current plot to render it in a hand-drawn thme.
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: "thme" should be "theme".

Suggested change
It works the same way as DARK, simply run the command "hand" on your current plot to render it in a hand-drawn thme.
It works the same way as DARK, simply run the command "hand" on your current plot to render it in a hand-drawn theme.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to 4
function hand(colors_in, fallback)
% Usage: hand(colors_in)
%
% Hand-drawn-theme plots.
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hand now accepts a second argument (fallback), but the usage line and parameter docs still only describe colors_in. Please update the header comment to document the new parameter and its behavior (e.g., how to disable fallback / force font install).

Copilot uses AI. Check for mistakes.
function [font_name, font_size, font_angle] = check_font(fallback)
font_angle = 'normal';
font_size = 20;
font_name = 'xkcd Script';
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check_font() calls listfonts(), which is not available in GNU Octave. Since hand() calls check_font() regardless of isoctave(), this will break Octave support. Please branch on isoctave() and use an Octave-compatible font detection strategy (or skip the font check in Octave).

Suggested change
font_name = 'xkcd Script';
font_name = 'xkcd Script';
% In GNU Octave, listfonts() is not available; skip the font check there.
if isoctave()
% Octave will use 'xkcd Script' if installed, or fall back to its default.
warning('Skipping font availability check on GNU Octave; using font "%s" if available.', font_name);
return;
end

Copilot uses AI. Check for mistakes.
Comment on lines +88 to +92
fonts = {'Segoe Print', 'Pacifico', 'Times', 'default'};
for i = 1:length(fonts)
if any(ismember(fonts_avail, fonts{i}))
font_name = fonts{i};
break
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If none of the fallback fonts are found, font_name remains 'xkcd Script' even though it’s missing, which can cause later font-setting to fail. Ensure this code always assigns a safe default (e.g., 'default') when no listed fallback font is available.

Copilot uses AI. Check for mistakes.
HAND has been tested with MATLAB R2023b and R2026a and
GNU Octave versions 7.1.0, 8.3.0, 9.1.0, and 11.1.0 running on Windows 10, macOS, Linux RHEL 8 and Ubuntu 22.04.
HAND bundles the excellent "xkcd Script" font from [xkcd-font](https://github.com/ipython/xkcd-font).
Similar to DARK, HAND is coded using funtions native to MATLAB and GNU Octave without any dependencies on toolboxes or packages, making it highly portable.
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in README: "funtions" should be "functions".

Suggested change
Similar to DARK, HAND is coded using funtions native to MATLAB and GNU Octave without any dependencies on toolboxes or packages, making it highly portable.
Similar to DARK, HAND is coded using functions native to MATLAB and GNU Octave without any dependencies on toolboxes or packages, making it highly portable.

Copilot uses AI. Check for mistakes.
push:
paths:
- "**.m"
- ".github/workflows/ci.yml"
Copy link

Copilot AI Mar 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This workflow runs only on push. If the intent is to validate pull requests, add a pull_request trigger as well so CI executes for PRs before merge.

Suggested change
- ".github/workflows/ci.yml"
- ".github/workflows/ci.yml"
pull_request:
paths:
- "**.m"
- ".github/workflows/ci.yml"

Copilot uses AI. Check for mistakes.
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.

2 participants