17

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?

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • Closely related: How to suppress Tooltip in built-in templates?, unfortunately I've failed to find equivalent of FrontEndExecute@FrontEnd`FlushTextResourceCaches[] for expressions' caches. – Kuba Jul 19 '16 at 21:01
  • @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. – Mr.Wizard Jul 20 '16 at 07:13
  • off-topic question, is there somewhere a generic topic about With[{FER :=? – Kuba Aug 01 '16 at 10:16
  • @Kuba I added this to (121173) for easy future reference. Leonid writes in (744) that he learned this syntax from Szabolcs so I probably did too, and just did not remember right. Quite possibly it was discussed on Stack Overflow. – Mr.Wizard Aug 01 '16 at 10:33
  • @Kuba A likely origin of this (see comments): (8742627). – Mr.Wizard Aug 01 '16 at 10:39
  • @Mr.Wizard would something akin to what I did here work? By making the changes in a temporary directory it is like an in-place edit (although very crucially not). – b3m2a1 May 11 '17 at 16:56
  • @MB1965 That could be useful. Thanks. For my own needs manually editing a copy of the files has been acceptable. It seems you were also unable to figure out FrontEnd`SetValue, if it actually does anything. – Mr.Wizard May 11 '17 at 21:47
  • 1
    @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. – b3m2a1 May 11 '17 at 21:50
  • @MB1965 I only skimmed your code and I have not yet tried it, but I don't see you getting around the need to restart Mathematica. I mean for my example above the "manually called resource" would be changed but the "auto-complete popup" would not be changed until Mathematica is restarted; is that correct? Or are you successfully performing a from-file refresh mid-session? – Mr.Wizard May 11 '17 at 21:52
  • 2
    @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. – b3m2a1 May 11 '17 at 21:55
  • 2
    @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. – b3m2a1 May 11 '17 at 21:57
  • @MB1965 Nice. That will be useful indeed. +1 now. :-) – Mr.Wizard May 11 '17 at 21:58
  • @Mr.Wizard I put up an example of what I'm doing with a link to the package here. – b3m2a1 May 12 '17 at 01:47
  • @Mr.Wizard this is way after the fact, of course, but I found a comment by John Fultz that suggests that even editing the .tr won't get the KeyEventTranslation in. – b3m2a1 Aug 17 '17 at 07:56
  • @b3m2a1 I think by programmatically he meant from within Mathematica itself, as editing the resource file has been effective in multiple versions. Of course, it's not a supported function so it could change with any release; perhaps it already has as I still use v10.1 – Mr.Wizard Aug 17 '17 at 08:05
  • @Mr.Wizard sorry that's what I was getting at. I was hoping for a way to reload the resources without quitting or restarting Mathematica. – b3m2a1 Aug 17 '17 at 08:06
  • @b3m2a1 Oh, I understand now. Thank you for pointing that out. That likely applies here, but maybe other resources can be edited. And if not now, perhaps in another version. – Mr.Wizard Aug 18 '17 at 01:18
  • @Mr.Wizard other things can definitely be edited and reloaded within a session using that FrontEnd`FlushTextResourceCaches[] but I never figured out how to access those caches themselves. Maybe through Internal`CheckCache or something. – b3m2a1 Aug 18 '17 at 01:20

1 Answers1

4

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.

b3m2a1
  • 46,870
  • 3
  • 92
  • 239