As of https://github.com/google/xi-editor/pull/203 there will be support for tracking whether a document is in a "saved" state.
The PR notes that "This creates the following behavior: If new text is inserted and the deleted back to the original state, there are no unsaved changes". This behavior differs from what I'm used to in other applications, where "saved" is defined as there being no operations in the undo stack between the last save and the current position.
After typing a bunch of text and deleting it (which the user might want to undo, to try tweaking the added text to satisfaction or for other purpose), the editor will close without; this behavior differs from what I'm used to programs doing, including image editors and other text editors; no other program I know of considers document contents to determine if a document is modified-since-saving only undo stack state.
This was discussed at some length in IRC without a clear conclusion, so I'm submitting a bug for further discussion. The primary questions are:
Is there an advantage to the semantics already implemented, over what other programs do?
Is there an advantage to what other programs do, other than familiarity?
I have looked at Atom and VS Code.
Atom compares the file buffer with the contents stored on disk. If I add text and remove it, the document goes back to the saved state. If I delete contents and rewrite the same content again, the document goes back to the saved state.
VS Code marks the document as unsaved after any insertion or deletion and the only way to return to the saved state(without saving) is via undo.
If new text is inserted and the deleted back to the original state, there are no unsaved
changes; however, if existing text is deleted and retyped, there are now unsaved changes.
This surprises me a bit. As a user, I would expect either the fully undo stack based behaviour, or a fully content-based behaviour. With this, there may be some situations where the content matches and the document is in saved state, but other situations where the content matches and the documen is not in saved state. That somewhat devalues the state indicator, it never reliably converts whether I still need to save or I don't.
Personally I prefer the content-based behaviour. I think it matches well with the intuition behind the UI metaphors. I look at the save state to determine whether I need to save. I want to save if the string in the buffer is not equal to the string on disk. Atom implements this in the most straightforward way, by actually checking. Determining the state based on the undo stack seems to be based on programmer needs, not user needs. Just because other programs take the lazy route does not mean that all future programs should follow the same convention.
I think there's necessarily _some_ compromise on this issue. There are an infinite number of edit paths to a given buffer's contents, (e.g. any sequence of insertions and deletions, which may have been garbage collected) and so we can't fully rely on graph operations (e.g. rope-based diffs) as a source of 'document truth'. The only way we could ever track dirtiness purely in terms of buffer state would be by something like a hash, and that seems like a bit much. (I suppose we could do a rolling hash, which we keep consistently up to date with insertions and deletions? But this just seems like more work for little gain.) Anyway, I think @cbrewster's solution is a good one.
For what it's worth, Sublime does a similar thing to our current behaviour: typing and deleting back to original state is not considered a file change.
I think the simplest and most familiar behavior is to do what VS Code does. It isn't obvious what's "good enough" for a state-diffing solution, unless we go the whole way and compare the entire buffer with the file on disk, which still introduces surprises e.g. when other programs concurrently modify the file on disk.
I think we've settled on the current behaviour. If there's dissent it can be a new issue.
Most helpful comment
This surprises me a bit. As a user, I would expect either the fully undo stack based behaviour, or a fully content-based behaviour. With this, there may be some situations where the content matches and the document is in saved state, but other situations where the content matches and the documen is not in saved state. That somewhat devalues the state indicator, it never reliably converts whether I still need to save or I don't.
Personally I prefer the content-based behaviour. I think it matches well with the intuition behind the UI metaphors. I look at the save state to determine whether I need to save. I want to save if the string in the buffer is not equal to the string on disk. Atom implements this in the most straightforward way, by actually checking. Determining the state based on the undo stack seems to be based on programmer needs, not user needs. Just because other programs take the lazy route does not mean that all future programs should follow the same convention.