bitst0rm-pub / Formatter

🧜‍♀️ A Sublime Text plugin to beautify, minify, convert code: CSS, SCSS, Sass, HTML, XML, SVG,JS,JavaScript, JSON, GraphQL, Markdown, TypeScript, Vue, Lua, YAML, Go, Perl, PHP, Python, Ruby, Rust, Haskell, Dart, Swift, Crystal, Bash, Shell, SQL, CSV, C, C++, C#, Objective-C, D, Java, Pawn, Julia, Blade, LaTeX, D2, Graphviz, Mermaid, PlantUML, etc
Other
105 stars 22 forks source link

Fixes the format on save function #22

Closed llukad closed 1 year ago

llukad commented 1 year ago

Fixes the problem when the format on save function always leaves the file dirty. It just saves the file again after the formatting is complete.

(I am on Windows version of ST)

bitst0rm commented 1 year ago

Hello @llukad

Thanks for your pull req, Your commit does the job as advertised, but it was never intended to overwrite the original raw input file with the formatted dirty. In situations like crashes, accidental closing Sublime etc... the original file will be never lost. Users can manually save the formatted dirty over the original file with the 2. save hit. It is their choice with all the consequences, not Formatter. The commit does it automatic with the 2. save hit, i am not sure about the advantage.

I have added the new feature "new_file_on_format", together with "format_on_save" you will have the same result as expected. But in this case again, the original raw input file should never be overwritten on the disk.

You can check the "dev"-branch for the new feature for the next release update.

llukad commented 1 year ago

Oh, I see. I just wanted to use the plugin as such:

Edit a file -> Press Ctrl+S -> File gets formatted -> Formatted file is saved.

Because before it behaved like this:

Edit a file -> Ctrl+S -> File gets formatted -> File is still dirty -> Ctrl+S -> File gets formatted again? -> File is still dirty -> ...

That seems to make the format_on_save kind of broken... So If I wanted to actually save the formatted file without having the file be left dirty I had to disable format_on_save and format it manually and then save manually.

But I also see why someone would not want to have the original file auto formatted and replaced.

bitst0rm commented 1 year ago

On my Mac it behaved like this as expected: Edit a file -> Press Ctrl+S -> File get saved > File gets formatted -> Formatted file is dirty.

I do not have Windows to test, so could you please test this on your Windows for me to see what is going here, thanks:

"format_on_save": true, main.py: from:

class RunFormatEventListener(sublime_plugin.EventListener):
    @classmethod
    def on_pre_save_async(cls, view):
        is_selected = any(not sel.empty() for sel in view.sel())
        formatter = common.settings().get('formatters', {})
        if formatter and isinstance(formatter, dict):
            for key, value in formatter.items():
                regio = None
                if not is_selected:
                    # entire file
                    regio = sublime.Region(0, view.size())
                else:
                    # selections
                    for region in view.sel():
                        if region.empty():
                            continue
                        regio = region
                syntax = common.get_assign_syntax(view, key, regio, is_selected)
                if value.get('format_on_save', False) and syntax in value.get('syntaxes', []):
                    log.debug('Format-On-Save applied to Formatter ID: %s, with assigned syntax: %s', key, syntax)
                    view.run_command('run_format', {'identifier': key})

    @classmethod
    def on_post_save_async(cls, view):
        _unused = view
        if common.settings().get('debug', False):
            # For debug and development only
            common.reload_modules()

replace with:

class RunFormatEventListener(sublime_plugin.EventListener):
    @classmethod
    def on_post_save_async(cls, view):
        _unused = view
        is_selected = any(not sel.empty() for sel in view.sel())
        formatter = common.settings().get('formatters', {})
        if formatter and isinstance(formatter, dict):
            for key, value in formatter.items():
                regio = None
                if not is_selected:
                    # entire file
                    regio = sublime.Region(0, view.size())
                else:
                    # selections
                    for region in view.sel():
                        if region.empty():
                            continue
                        regio = region
                syntax = common.get_assign_syntax(view, key, regio, is_selected)
                if value.get('format_on_save', False) and syntax in value.get('syntaxes', []):
                    log.debug('Format-On-Save applied to Formatter ID: %s, with assigned syntax: %s', key, syntax)
                    view.run_command('run_format', {'identifier': key})
        if common.settings().get('debug', False):
            # For debug and development only
            common.reload_modules()
llukad commented 1 year ago

On Windows it behaves like this:

https://github.com/bitst0rm-pub/Formatter/assets/85436080/f27d4bbe-9695-43dc-ac82-c669c631392e

Like you can see, each time that I save the file, it gets formatted again (even if nothing needs to be formatted) and so I can't get the file into a non-dirty state.

I am using Prettier in this example.

bitst0rm commented 1 year ago

Thanks for the video. in the "formatter.py", line 46, could you please replace to see from: if view.is_scratch() or view.is_read_only() or view.window() is None: replace to: if view.is_read_only() or view.window() is None:

and very important: restart Sublime to reload the modules.

llukad commented 1 year ago

It seems to still behave exactly the same as in the video I sent.

bitst0rm commented 1 year ago

I rewrote formatter_prettier.py https://github.com/bitst0rm-pub/Formatter/commit/299af3a555718548bc59e94128c0b26b6da35846 The problem is i could not reproduce the issue on mac to fix it.

llukad commented 1 year ago

For me, even after the rewrite, it's still not working. My pull req fixes it for me, but maybe it should be changed so all my changes are optional, so people can enable it if they have this issue?

bitst0rm commented 1 year ago

I looked your video again, the tiny circle button on the tab showing current dirty state can be confused to lead thinking file is endless dirty, but it is not, only view is endless dirty.

After first Press Ctrl+S the visual view will never forever be back to none-dirty, but the dirty codes on the current view will physically be saved to the file by the next Press Ctrl+S. This is all correct. You can monitor this with an second Text editor != Sublime for the saved file in the background:

Open a file A (View: none-dirty) > Edit file A (View: dirty) > Press Ctrl+S > File A gets saved on disk with all edited things (Physical: none-dirty) > File A gets formatted (View: dirty) [1] > Press Ctrl+S > File A gets saved on disk with formatted code from [1] (Physical: none-dirty) > File A gets formatted (View: dirty) [2] > Press Ctrl+S > File A gets saved on disk with formatted code from [2] (physical: none-dirty) > File A gets formatted (View: dirty) ... and so on.

Because each times you Press Ctrl+S the file gets formatted again, means the view gets modified again, so the view is dirty, endless dirty. But file gots saved, so the file is none-dirty.

And to your question: If Formatter behaves like steps above, then everything is logic and correct. Your pull req starts with line 136: if view.is_dirty(): This is problematical, none-dirty file (e.g fresh opening file) will be ignored to get formatted.