I want to run some code automatically after saving my notebook. Is there a $ variable or setting for this?
2 Answers
Yes, it can be easily implemented with FrontEndExecute, e.g.:
SetOptions[EvaluationNotebook[], NotebookEventActions ->
{{"MenuCommand", "Save"} :> Print["HEY"], PassEventsDown -> True}];
You can insert any code instead of Print command
Edit
Above code executes Print["HEY"]
before saving the notebook, because you catch the event at the beginning, do some work and release it back to program with PassEventsDown
.
To evaluate some code after saving - one has to handle full event manually. The simplest would be just remove PassEventsDown
and instead of Print["HEY"]
write (NotebookSave[]; Print[123])
:
SetOptions[EvaluationNotebook[], NotebookEventActions ->
{{"MenuCommand", "Save"} :> (NotebookSave[]; Print[123])}]
Unfortunately, this will "intercept" also saving event triggered by "Save As" command and it will always save file with its old name even if we change name in "Save As" window.
-
1$\begingroup$ @funnypony If you replace
"HEY"
withNotebookFileName[]
and try to save notebook as file with different name, you'll get old file name, or$Failed
if notebook was not saved before. So it seems that this code is evaluated before saving the notebook. Is there a way to really evaluate code after notebook was saved? $\endgroup$– jkuczmCommented Dec 7, 2014 at 17:04 -
1$\begingroup$ @jkuczm yes it saves after Print just because you catch the event at the beginning, do some work and release it back to pogram with passeventsdown. To evaluate some code after saving - one has to handle full event manually. The simplest would be just remove passeventdown and instead Print[] write
{NotebookSave[]; Print[123]}
but! it will work only with saved notebooks, it can't handle SaveAs command.. Unfortunately, I don't know how to catch only SaveAs command.. $\endgroup$ Commented Dec 8, 2014 at 13:48 -
$\begingroup$ @funnypony +1 I found your answer useful nonetheless. $\endgroup$– jkuczmCommented Dec 8, 2014 at 23:04
Adding to @funnypony's answer, if we really need to execute code after saving a notebook and we don't want to break "Save As" functionality, then we can use following workaround.
- In
"Save"
action useNotebookSave[]
and code we want to execute after it. - In
"SaveRename"
action put code assigning new"Save"
notebook action. This new"Save"
action will restore previousNotebookEventActions
and pass events down.
Whole thing would look like this:
$notebookEventActions = {
{"MenuCommand", "Save"} :> (
Print["before Save: ", NotebookFileName[], " last modified: ",
FileDate@NotebookFileName[]];
NotebookSave[];
Print["after Save: ", NotebookFileName[], " last modified: ",
FileDate@NotebookFileName[]]
),
{"MenuCommand", "SaveRename"} :> (
SetOptions[
EvaluationNotebook[],
NotebookEventActions -> {
{"MenuCommand", "Save"} :>
SetOptions[
EvaluationNotebook[],
NotebookEventActions -> $notebookEventActions
],
PassEventsDown -> True
}
];
NotebookSave[Interactive -> True]
)
};
SetOptions[EvaluationNotebook[], NotebookEventActions -> $notebookEventActions]
Now using "Save" command will print "before Save: ..."
text, then save notebook, then print "after Save: "
text. Using "Save As" will work as if it was not modified at all.