WeBWorK Main Forum

by Andrew Dabrowski -
Number of replies: 14
There is or was a function called "WeBWorK::PG::ImageGenerator::addToTeXPreamble" traces of which I have detected in cyberspace. I was hoping to be able to use this function to add "\newcommand" latex macros to my code.

That is, I was hopping to be able to write
and then be able to call this new macro from within a PGML section by
[ \test ]
Will this hope have to be abandoned?

by Alex Jordan -
Here is a workaround, if nothing better comes about.

$macro = '\newcommand{\test}{\mbox{Test Succeeded!}}'; BEGIN_PGML Any math that uses the macro: [[$macro]1+1=2 \test].

A second instance:

by Davide Cervone -
Note that this only affects mathematics in image mode, and the imagegen property is only available in that mode. So one would need to handle the other output modes separately.

by Alex Jordan -
For another project, I recently had to investigate using LaTeX macros in pg files, and Davide points out a fundamental issue. Since you need to be considering images, MathJax, and print, (and anything else?), addToTeXPreamble alone is not going to be enough.

My solution was basically what I posted earlier, inserting the \newcommand into each instance of math where it is necessary. (My project inserts such things using automation, so it's not as tedious as it sounds.)

By the time you work out how to handle all the multiple output modes, it may end up being more work than just doing something like what I posted. Not to mention, who knows what future output modes might come into play? Directly using the macro code seems safe for such things, while a mode-by-mode approach might not have longevity.

The next thing that occurs to me would be to somehow modify the output of [...] and friends within a PG block to automatically insert the macros, but I wouldn't want to mess with tweaking PGML to do that.

by Andrew Dabrowski -

by Davide Cervone -
Here is an approach that I think should work. Start the problem with
$macros = join("", "\newcommand{\myMacro}{\mbox{This is myMacro!}}", ); if ($displayMode eq "HTML_dpng") {
$rh_envir->{imagegen}->addToTeXPreamble($macros);
} else {
TEXT(MODES(
TeX => "{".$macros, HTML => qq{ $$macros$$ }, )); } and use \myMacro in the problem as needed. At the end of the problem, add TEXT("}") if$displayMode eq "TeX";

This should create the macros in the way needed by the various output modes (at least for hardcopy, MathJax, and Image modes), and localizes the macros to the given problem (except for MathJax mode in the library browser since macros in MathJax are global to the page).

One could, of course, create commands like

BeginTeXMacros(
"\newcommand{\myMacro}{\mbox{This is myMacro}}",
);
...
EndTeXMacros();

that hide the mechanics of it, and load them from a local macro file if you want to do this in many problems.

Of course, the image-mode output does suffer from the same caching issue that we see below, so I would recommend doing development using MathJax mode instead.

by Andrew Dabrowski -
Stupid I am, but I don't want you to think I'm lazy: I actually did see that page before starting this thread, but that call doesn't seem to work. The following code

$rh_envir->{imagegen}->addToTeXPreamble("\newcommand{\test}{\mbox{The test succeeded!}}"); BEGIN_PGML [ \test ] END_PGML results in nothing being printed. (And I am viewing the problem in image mode.) At least it doesn't produce an error, so there's hope. Btw, what is$rh_envir exactly? Is it more than just a reference to %envir? It's not well documented.

And just to satisfy my curiosity, why doesn't the call
work? Is WeBWorK shielded from .pg files?

by Michael Gage -
OK.

Did it work with the example given on the page (which modifies the manner of printing vectors)?  I believe that is the original use case that John Jones wrote it for.

I can't troubleshoot the macro right this minute and as Alex points out this macro, written before MathJax mode existed, may no longer be the best way to handle this situation.  I think I can answer your last two questions however.

$rh_envir (the rh is supposed to stand for reference-to-a-hash) is an anonymous hash passed into the PG environment. It is then unpacked into a regular hash (named) %envir in the file pg/macros/PG.pl so as to be more conveniently available. Some of the macro files (and some PG problems) use$rh_envir directly, possibly because it is less likely that the contents have been modified from within a PG problem, or possibly for no particular reason -- just that it is available.

addTeXPreamble("TeXcommand_here") is a method which means that it requires an object in order to get its job done. For example it has to store this TeX command somewhere and the object gives it the information needed as to where to store it.   The image generator object (which knows how to use this method) is $rh_envir->{imagegen} and one of these image generator objects is created for each PG problem. Since perl shows you how things work "under the hood" it demystifies the concept of "object method" somewhat.$rh_evir->{imagegen}>addTeXPreamble("TeXcommand_here") translates into a subroutine call of the
form WeBWorK::PG::ImageGenerator::addToTeXPreamble()($rh_envir->{imagegen}, "TeXcommand_here"). Methods are merely subroutines whose first step is to accept a "$self" object.

If a subroutine in a package starts with
my $self = shift; it's a method and called by$obj->subroutine_name() syntax.  If it doesn't it's a function and called via subroutine_name() (with the package name prepended if necessary).