To show a "modified" indicator, we should also choose an appropriate reference/origin from which it is tracked. A reasonable choice would either be the last notebook save or the time the cell was last evaluated. Since your intention is to track all modifications and not only modified + evaluated, I'll use the last save point as the reference.
The following is a proof of concept of a "cell modified" indicator. I'll discuss possible improvements and current limitations after the code:
1. Action when cell is modified
As mentioned above, I've chosen the time when the file was last saved (modification time on disk) as the reference point. The following function sets a cell's background to a light shade of gray if the cell modification time (as given by CellChangeTimes) is after the file modification time.
modifiedCell := With[{
fileMod = "FileModificationTime" /. NotebookInformation[EvaluationNotebook[]],
cellMod = If[# != {}, Last@Flatten@#, -Infinity] &@CurrentValue[CellChangeTimes]},
Switch[fileMod,
"FileModificationTime",
None,
_?NumericQ,
If[fileMod < cellMod || cellMod === {},
SetOptions[EvaluationCell[], Background -> GrayLevel[0.95]],
SetOptions[EvaluationCell[], Background -> White]]
]
]
2. Action when notebook is saved
Given the choice of our reference time, it is necessary to reset the cell backgrounds (here, the "modified indicator") when the notebook is saved. The following function sets the background of all input cells in the notebook to White (you can also use your default background, if it's different or Background -> None).
notebookSaved := SetOptions[#, Background -> White] & /@
Cells[EvaluationNotebook[], CellStyle -> "Input"]
Thanks to Michael for the tip re: using Cells directly instead of Cells + NotebookFind.
3. Setting up event handlers & piecing it together
All that remains is to set up appropriate event handlers — CellEventActions for when a cell is modified ("modified" here means a keypress in that cell) and NotebookEventActions for when the notebook is saved — and make the appropriate changes. I prefer to modify the stylesheet and add the changes to the "Input" style for the notebook. If you want other cells to also exhibit this behaviour, you'll have to add it yourself.
SetOptions[EvaluationNotebook[], {
StyleDefinitions -> Notebook[{
Cell[StyleData[StyleDefinitions -> "Default.nb"]],
Cell[StyleData["Input"],
CellEventActions -> {
"KeyDown" :> modifiedCell,
PassEventsDown -> True
},
Background -> GrayLevel[1]
]},
Saveable -> True, StyleDefinitions -> "PrivateStylesheetFormatting.nb"
],
NotebookEventActions -> {
{"MenuCommand", "Save"} :> notebookSaved,
PassEventsDown -> True
}
}]
4. Current limitations
CellEventActions is triggered before the cell is actually modified. This means that the first change after a save point cannot trigger the change in background, because the CellChangeTimes still refers to the previous state (or in the case of a new cell, CellChangeTimes is empty). While this is a wee bit limiting, in practice, I've never had to make just 1 key press worth of change (without even pressing a modifier/arrow key in the process), so it might not be all that bad.
CellChangeTimeis a good choice but does not deal with the case I said. – HyperGroups Jun 23 '13 at 02:24Outputstatements – William Jun 24 '13 at 03:36