sublimehq / sublime_text

Issue tracker for Sublime Text
https://www.sublimetext.com
811 stars 39 forks source link

`view.is_dirty()` out of sync when file is deleted #6490

Closed titoBouzout closed 1 month ago

titoBouzout commented 1 month ago

Description of the bug

view.is_dirty() out of sync when file is deleted, it returns False when it should return True nvm Im wrong, but there's an issue

  1. install the command quoted bellow
  2. drag a drop a file from desktop to ST
  3. focus a new view in ST
  4. delete the file from desktop
  5. add the following command to the tab context menu, and run it on the empty view
  6. it will prompt for saving instead of being closed
//  Tab Context.sublime-menu
[{
    "command": "close_all_other_dirty_tabs",
    "caption": "Close Others Dirty"
}]
# user/is_dirty.py
class close_all_other_dirty_tabs(sublime_plugin.WindowCommand):
    def run(self):
        window = sublime.active_window()
        _view = window.active_view()
        for view in window.views():
            if view != _view:
                if view.is_dirty():
                    print("is dirty")
                    view.set_scratch(True)
                    view.run_command("set_scratch", True)
                view.close()

Steps to reproduce

above

Expected behavior

My use case was to "close other tabs even if dirty", so one could say that my view.is_dirty() check was useless, but I still expected it to work, so that put me off for a while.

In any case, if I want to create the command "close others dirty tabs", leaving open non-dirty tabs, then I won't be able todo so with this bug.

Actual behavior

already described

Sublime Text build number

4178

Operating system & version

Windows 10

(Linux) Desktop environment and/or window manager

No response

Additional information

Additionally, there's some sort of race condition, if files open, get deleted and recreated in rapid succession, it will remain dirty, even if the file contents it's the same.

  1. file is open and saved
  2. file gets deleted
  3. file gets created with same content
  4. file is marked as dirty and remains dirty

OpenGL context information

No response

titoBouzout commented 1 month ago

Uh, now that I think, the value is right. If the file was deleted, and recreated with the same content, then is not dirty.

The issue is somewhere else, ST thinks the file has unsaved changes, the UI shows hints (like the tab icons changing color) its unsaved, and when trying to close it, it asks for saving.

I can't tell where the problem is, but something is not right.

deathaxe commented 1 month ago

Related with #6503

You are probably confused by deleted and modified files being displayed with the same close button icon.

Technically "deleted" and "modified" states are independent. The real file state is a combination of both.

deleted dirty description
0 0 unmodified content of an existing file
1 0 unmodified content of a deleted file
0 1 modified content of an existing file
1 1 modified content of a deleted file

That's also expressed by the "Save As..." dialog's message.

grafik

To suppress the dialog for unmodified deleted files, a check for valid view.file_name() and not os.path.exists(view.file_name()) is required in addition to view.is_dirty()

Following modification to your plugin is required

# user/is_dirty.py
import os
import sublime
import sublime_plugin

class close_all_other_dirty_tabs(sublime_plugin.WindowCommand):
    """Close all deleted or modified views without confirmation."""
    def run(self):
        window = sublime.active_window()
        _view = window.active_view()
        for view in window.views():
            if view != _view:
                if view.file_name() and not os.path.exists(view.file_name()):
                    print("is deleted")
                    view.set_scratch(True)
                elif view.is_dirty():
                    print("is dirty")
                    view.set_scratch(True)
                view.close()

Note: A related solution can be found at https://forum.sublimetext.com/t/do-not-prompt-to-save-deleted-files/72990/3, which can be commanded to save or not save closed views via arguments.

Conclusion

The view.is_dirty() function is working as expected.

titoBouzout commented 1 month ago

Thanks @deathaxe for the explanation, indeed view.is_dirty() was/is working as expected.

My confusion came from that after the file being restored, the UI(not the api) still showed the file as being "dirty". Such as asking for saving, that was in 4178, I can't seem to reproduce that behavior anymore with 4183. So something must have changed.

I suppose we are good to close the issue?