5
$\begingroup$

As we know, owing to the set of SetOptions[InputNotebook[], AutoGeneratedPackage -> Automatic], a .m file will be generated automatically by the Mathematica front end.

  • But in Mathematica 11 we use .wl file rather than .m file.
  • Also, the function AutoGeneratedPackage has not been fully integrated into the long-term Wolfram Language, and is subject to change.

So, it comes a question how to make a parallel auto-generated .wl package from a .nb notebook rather than using AutoGeneratedPackage

$\endgroup$
  • 1
    $\begingroup$ "WL" is not even in the Listing of All Formats. The Package format documentation only talks about .m files. $\endgroup$ – Karsten 7. Dec 6 '16 at 5:54
  • $\begingroup$ "But in Mathematica 11 we use .wl file rather than .m file." <- This is not true. You can use the .wl extension if you want to. But you can also use .m. I see no disadvantage to using .m, but I do see advantages, e.g. backwards compatibility. All files in the installation directory still use .m. Why would you inconvenience yourself by using hacks like in the answer below just to have .wl? What do you expect to gain? $\endgroup$ – Szabolcs Dec 6 '16 at 18:48
2
$\begingroup$

UPDATE 2.0

I just discovered this wonderful answer by Mr. Wizard on saving as a package via FrontEndTokenExecute and so this is an even more trivial task now:

simply call

FrontEndTokenExecute[
 FrontEnd`InputNotebook[], "SaveRename", {StringReplace[
   NotebookFileName[], ".nb" -> ".wl"], "Package"}]

in your {"MenuCommand","Save"} binding and use PassEventsDown->True. Note that this preserves constructs like "Input" cells and whatnot so Karsten7's idea is the definite winner if you're looking for the direct AutoGeneratedPackage analog. On the other hand, the ability to gather the data from the notebook in a more compressed package format is pretty useful.

UPDATE

Per Karsten7's comment, it suffices to copy a newly generated .m to a .wl so assuming AutoGeneratePackage is set the code could be as simple as

SetOptions[
 EvaluationNotebook[],
 NotebookEventActions -> {
   {"MenuCommand", "Save"} :> 
     (
       NotebookSave[];
       RenameFile[
         StringReplace[NotebookFileName[],".nb"->".m"],
         StringReplace[NotebookFileName[],".nb"->".wl"]
         ]
     )
   }
 ]

Note that we really do have to call NotebookSave[] rather than just using PassEventsDown because this event is called before the save event would have been called. This can lead to issues with Save As... but assuming one simply saves the thing normally, it is really this easy.

I'm keeping the original code below as it does give a mechanism to save things other than just IntializationCell and InitializationGroup constructs which is potentially useful.

ORIGINAL

Using the copy-as-plaintext scheme here one can write a custom save as package function and bind it to the {"MenuCommand","Save"} event and have this do the exporting. The following will do this for all "Code" cells. One could tweak it to work for all cells with InitializationCell set. The real difficulty is getting it to work for InitializationGroup cells, too, but that should really just be a matter of getting all the child cells of InitializationGroup cells.

If all your code is in "Code" cells, though, this should work for you:

getCodeString[cellStyles__] :=
  First@
   FrontEndExecute[
    FrontEnd`ExportPacket[
     Cases[
      First@
       NotebookTools`FlattenCellGroups@
        NotebookGet@EvaluationNotebook[],
      Cell[_, Alternatives@cellStyles, ___]
      ], "PlainText"]
    ];
SetOptions[
 EvaluationNotebook[],
 NotebookEventActions -> {
   {"MenuCommand", "Save"} :>
    With[{
      file =
       OpenWrite@FileNameJoin@{
          NotebookDirectory[],
          FileBaseName@NotebookFileName[] <> ".wl"
          },
      dnu = 
       DynamicUpdating /. 
        AbsoluteOptions[EvaluationNotebook[], DynamicUpdating]},
     SetOptions[EvaluationNotebook[],
      DynamicUpdating -> False
      ];
     WriteString[
      file,
      getCodeString["Code"]
      ];
     Close@file;
     SetOptions[EvaluationNotebook[], DynamicUpdating -> dnu]
     ]
   }
 ]

Interestingly enough ".wl" seems not to be recognized as an export type in Export.

$\endgroup$
  • 1
    $\begingroup$ Wouldn't renaming the .m file to a .wl file be enough? mathematica.stackexchange.com/q/98981/18476 $\endgroup$ – Karsten 7. Dec 6 '16 at 5:58
  • $\begingroup$ It doesn't works. NotebookTools is not exist in my environment(Windows 10,Mathematica 11.0) $\endgroup$ – xiang Dec 6 '16 at 7:26
  • $\begingroup$ @Karsten7 That would certainly be enough, although it still requires a little bit of hackiness, I'll add an update to the answer. I was simply going off the top of my head. $\endgroup$ – b3m2a1 Dec 6 '16 at 10:10
  • $\begingroup$ @xiang I believe there is no package with that name, but that function ought to exist. I have Mathematica 11.0 as well. The function will appear not to be there but it in fact is. Try running Names@"NotebookTools`*" and my guess is that you'll see a long list of functions you didn't know were in Mathematica. $\endgroup$ – b3m2a1 Dec 6 '16 at 10:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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