17
$\begingroup$

A number of special definitions are loaded from .tr files on Front End initialization and are accessible via FrontEndResource. These are used among other things for various menus and toolsbars, e.g.:

FrontEndResource["FEBitmaps", "HomeIconHot"] // ToExpression

FrontEndResource["FEExpressions", "HelpViewerToolbar"] // CellPrint

FrontEndResource["ContextMenus", "GraphicsBox"]

FrontEndResource["ColorSchemeSelector"] // CellPrint

The .tr resource files can be edited to change these as I proposed for Can you make the new "Choose color scheme" helper larger? and Is it possible to insert new colour schemes into ColorData? It would be much nicer to be able to edit these after they are loaded from within Mathematica. One can Unprotect FrontEndResource and modify the definition but this does not actually change what is displayed in the Front End.

As a simple example I would like to make the Color Scheme Selector a little wider so that it does not have a pointless horizontal scroll bar on my system. I attempt:

Unprotect[FrontEndResource];

With[{FER := FrontEndResource["ColorSchemeSelector"]},
  FER = FER /. {180, Automatic} -> {195, Automatic};
]

The manually called resource is now wider:

FrontEndResource["ColorSchemeSelector"] // CellPrint

enter image description here

However the auto-complete popup for Color is not:

enter image description here

On examination this is not too surprising since the actual definition of FrontEndResource is:

FrontEndResource[name_] := 
  MathLink`CallFrontEnd[FrontEnd`Value[FEPrivate`FrontEndResource[name]]];

FrontEndResource[name_, sub_] := 
  MathLink`CallFrontEnd[FrontEnd`Value[FEPrivate`FrontEndResource[name, sub]]];

It seems logical that the Front End would make this lower level call directly, bypassing System`FrontEndResource. My problem is that I don't know how to redefine this FrontEnd`Value. Names finds a FrontEnd`SetValue which sounds promising but I haven't figured out how to use it.

How can I change this Front End Resource in a way that affects all appearances of the menu?

$\endgroup$
18
  • $\begingroup$ Closely related: How to suppress Tooltip in built-in templates?, unfortunately I've failed to find equivalent of FrontEndExecute@FrontEnd`FlushTextResourceCaches[] for expressions' caches. $\endgroup$
    – Kuba
    Commented Jul 19, 2016 at 21:01
  • $\begingroup$ @Kuba Thanks for reminding me of that question, or more specifically your answer; I had forgotten. Even with that I see that you had to write to a .tr file rather than directly editing things in memory. Perhaps these definitions are simply read only but I am hoping for authoritative confirmation of that before coming to a conclusion. $\endgroup$
    – Mr.Wizard
    Commented Jul 20, 2016 at 7:13
  • 1
    $\begingroup$ @Mr.Wizard I've only ever seen it used as FrontEnd`SetValue[FEPrivate`Set[CurrentValue[spec],val]]. That works fine, but doesn't really help us here. Once I figure out how to make the packets work I'll post a solution editing at the DownValues level on FrontEnd`Value, but I have no experience with these WTSP packets so it's all very confusing. $\endgroup$
    – b3m2a1
    Commented May 11, 2017 at 21:50
  • 2
    $\begingroup$ @Mr.Wizard I get around that by prepending my temporary path to {PrivatePaths, "TextResources"} then by calling FrontEnd`FlushTextResourceCaches[]. It reloads everything as one would hope--as long as one uses a resource name already known to the system. $\endgroup$
    – b3m2a1
    Commented May 11, 2017 at 21:55
  • 2
    $\begingroup$ @Mr.Wizard one caveat is that I haven't been able to get successful reloading with KeyEventTranslations.tr although I'm gonna keep playing with it. Reloading the menus works fine if you call ResetMenusPacket[{Automatic,Automatic}] (found in the PacletManager code) so I'm working on editing the MenuSetup.tr right now. $\endgroup$
    – b3m2a1
    Commented May 11, 2017 at 21:57

1 Answer 1

4
$\begingroup$

This is more comment than answer as you want in-memory modification, but it is possible to force the text resources to be reloaded. You do this with, e.g.,

FrontEndExecute@
 FrontEnd`FlushTextResourceCaches[]

So you can make a new text resource in $UserBaseDirectory and have that reload. For example, let's make a new TR for the file headers:

$headersTR =
  FrontEndExecute@
   FrontEnd`FindFileOnPath[
    "FileHeaders.tr",
    "PrivatePathsTextResources"
    ];
$newHeadersTR =
  StringReplace[$headersTR,
   $InstallationDirectory -> $UserBaseDirectory
   ];
CreateDirectory[DirectoryName@$newHeadersTR,
  CreateIntermediateDirectories -> True];
Export[
  $newHeadersTR,
  "
  @@resource PackageHeader
  (*?__?*)

  @|
  ",
  "Text"
  ];

Then reload the headers:

FrontEndExecute@FrontEnd`FlushTextResourceCaches[]
FrontEndResourceString["PackageHeader"]

"(*?__?*)
"

And that'll change the package header in all your auto-generated .m files.

Note that this isn't in-memory modification, but I'm not wholly these are always stored in memory, as sometimes deleting a file causes the FE to spit an error when you try to load a resource from that file.

On the other hand, something definitely is stored in memory. E.g., try deleting that new package header TR and loading the header again:

DeleteFile[$newHeadersTR]
FrontEndResourceString["PackageHeader"]

"(*?__?*)
"

So that's there until the cache is flushed.

Update:

Here's a way to get it to spit an error:

Export[
  $newHeadersTR,
  "
  @@resource PackageHeader
  (*?__?*)

  @|
  ",
  "Text"
  ];
FrontEndExecute@FrontEnd`FlushTextResourceCaches[]
DeleteFile[$newHeadersTR];
FrontEndResourceString["PackageHeader"]

$Failed

Clearly the FlushTextResourceCaches found that "PackageHeader" was in $newHeadersTR, but didn't load it. My guess would be that it got added to "ResourceMap.pbf" (see below) or something, but the load doesn't get performed until later.

Cache files:

Just as one last note on these caches, there're these files:

FileNames["ResourceMap.pbf",
 FileNameJoin@{$UserBaseDirectory, "FrontEnd"},
 Infinity
 ]

which are what actually get overridden when you call:

FrontEndExecute@
 FrontEnd`FlushTextResourceCaches[]

And they're some scrambled binary format, but if you look at them in plain-text view you see the file names where the resources are stored, e.g. I found:

"/Applications/Mathematica.app/Contents/AddOns/Applications/NotebookTemplating/FrontEnd/TextResources/NotebookTemplatingResources.tr"

in it.

So presumably this file gets used as the "ResourceMap" to the front-end to tell it from where to load resources it doesn't have in memory. That may also explain why deleting a cached resource file sometimes throws errors.

$\endgroup$
1
  • $\begingroup$ Possibly the only answer possible at this time. Thanks for taking the time to write it up in detail. $\endgroup$
    – Mr.Wizard
    Commented Aug 18, 2017 at 19:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.