benknoble / vim-racket

vim bundle for Racket
MIT License
24 stars 4 forks source link

Formatting (gqap or similar) replaces the buffer contents by an error message in case of error #11

Closed amosnier closed 1 year ago

amosnier commented 1 year ago

Tested at 1c02b65f30d01eb05049e0a3f1d7ddb84658457c.

To reproduce the issue:

(define

Press gpap (format current paragraph). The contents of the buffer will be changed to:

1:1:0: expected a `)` to close `(`
  context...:
   /usr/local/share/racket/collects/syntax/readerr.rkt:15:2: -raise-read-error
   .../match/compiler.rkt:559:40: f123
   /home/alain/.local/share/racket/8.8/pkgs/fmt/read.rkt:123:0: read-top
   /home/alain/.local/share/racket/8.8/pkgs/fmt/main.rkt:27:0: program-format
   /home/alain/.local/share/racket/8.8/pkgs/fmt/raco.rkt:115:0
   body of "/home/alain/.local/share/racket/8.8/pkgs/fmt/raco.rkt"
   /usr/local/share/racket/collects/raco/raco.rkt:41:0
   body of "/usr/local/share/racket/collects/raco/raco.rkt"
   body of "/usr/local/share/racket/collects/raco/main.rkt"

At this point, I can of course undo, but somehow that does not feel so sane. If I start using auto-formatting upon save, for instance, this potentially becomes hard to undo.

The explanation for this is https://github.com/sorawee/fmt/issues/44, i.e. not really this plugin's issue, but as long as that issue is not solved, using raco fmt as a format external program does not feel like a very good solution.

Hoping for a solution for that issue and looking forward, I also wonder whether using raco fmt as formatprg is the best possible choice. In particular, I wonder whether it would be better to point equalprg to it instead. This idea is somewhat related to https://github.com/sorawee/fmt/issues/43. Given that raco fmt does not format comments, and given that there is no real plan to change that, leaving formatprg empty would allow the users to use the default formatter, which typically works well enough, for comments.

amosnier commented 1 year ago

For the record, I have created raco-fmt-or-cat for my own short term needs.

benknoble commented 1 year ago

I don't use any autoformatting, but the issue is still relevant (for example: gq also errors if fmt is not installed).

Manually, I u and use gw. That also handles comments, since it uses the builtin formatter.

One could wrap raco fmt with systemlist() and do all the plumbing in Vim; but, that re-invents all of gq's "filter" ability just to do a little error checking. I don't want to support that kind of code long-term; I would rather lean on the built-ins.

The good news is this: gq still sets v:shell_error. Check it for 0 in any auto-formatting that runs gq.

If you don't like formatprg=raco\ fmt, then I suggest you put setlocal formatprg= in ~/.vim/after/ftplugin/racket.vim.

The program is very much a formatter, not an indenter, so equalprg is not my preference. I tend to leave = to the 'lisp' indenter.

[Apologies in advance for the lack of quoted replies and the presence of disjointed paragraphs; I am in a bit of a hurry.]

amosnier commented 1 year ago

Thanks @benknoble for the quick answer. I had overlooked gw so it is good that you mention it.

And your view about equal vs format is interesting. I am kind of ambivalent myself, since with a good code formatter, an indenter mostly feels redundant. So that would leave the equal unused in a typical workflow of mine, while the default formatter typically is quite competent at formatting comments in various languages. There is as you mention the difference between gq and gw too, but if I understand correctly, that difference is a mix of tool and motion, which I do not find very clean, so I'd rather limit myself to using the difference in motion.

Thanks finally for the recommendation about after/plugin, which I definitely do not master.

Slightly related to the Vim configuration structure, one thing I kind of lack in this plugin is more documentation. My main question would be: what does this plugin actually claim the solve for me? That it provides some support for Racket is pretty much all I know right now (apart from the specific formatprg configuration, obviously) and that feels kind of vague. Also, am I right that this plugin does not include some :help documentation under Vim? Please do not take these questions as criticism. That the maintainers would focus on functionality rather than documentation would feel perfectly understandable, we all have a day job to attend to after all.

benknoble commented 1 year ago

And your view about equal vs format is interesting. I am kind of ambivalent myself, since with a good code formatter, an indenter mostly feels redundant. So that would leave the equal unused in a typical workflow of mine, while the default formatter typically is quite competent at formatting comments in various languages. There is as you mention the difference between gq and gw too, but if I understand correctly, that difference is a mix of tool and motion, which I do not find very clean, so I'd rather limit myself to using the difference in motion.

I'm not sure I follow what you mean by difference in tool and motion; by tool I am sure you mean formatprg versus internal formatter. By motion, perhaps you mean that gw doesn't move the cursor, while gq does? (I typically reserve the word "motion" in Vim contexts for, well, :help motion items.)

At any rate: based on my prior comments, I'm tempted to close this issue as "wontfix" just to clarify my position; I would need a persuasive argument to make changes at this point. I'll wait for your response before I make any hasty decisions, though, and that doesn't mean the rest of the discussion [see below] isn't valuable.

Thanks finally for the recommendation about after/plugin, which I definitely do not master.

Please let me know if you have more questions about runtimepath structure (but perhaps this is not the best "forum" for that? I'm pretty active at vi.stackexchange.com, which has a chat platform.).

Slightly related to the Vim configuration structure, one thing I kind of lack in this plugin is more documentation. My main question would be: what does this plugin actually claim the solve for me? That it provides some support for Racket is pretty much all I know right now (apart from the specific formatprg configuration, obviously) and that feels kind of vague. Also, am I right that this plugin does not include some :help documentation under Vim?

This is correct; see #6 for example. The README could certainly offer a better taste of the support offered, and a help page could detail usage, configuration, etc. I just haven't written it yet. (And it could probably include mention of the problem in this issues title and suggestions for handling it.)

One answer to your question: some of this plugins basic files are included in Vim's runtime files (or outdated versions of them, anyway). This would include syntax, ftplugin, indent, and compiler files IIRC. Syntax and indent support should sound obvious (if not look it), although the ftplugin and compiler files might be less so. They provide Racket-specific mappings (e.g., for looking up documentation) and :compiler/:make support. See the help pages for these topics, and the corresponding files, if you're interested.

The second answer to your question is that this plugin, in addition to what's occasionally include in the Vim runtime files, offers unique filetype detection for Racket: each #lang gets its own filetype. This means it is possible for each #lang to have their own syntax, indent, ftplugin, etc., files. This is a good thing, since some #langs have very different syntax than others. There is also an undocumented shortcut for #langs that should behave identical to others (e.g., #lang racket/gui should just have filetype racket; it's not so different as to require special support).

This filetype detection is not without its downsides: making LSPs and similar work requires you to redirect non-racket filetypes as though they were racket (with ALE, for example, I :let b:linter_aliases = 'racket'). See also #5, where shebang lines interfere with filetype detection rather poorly. So, some people dislike it; this is why it is not yet included in Vim's runtime files (and why others choose to use an old commit of this repository or its upstream, though in doing so they miss improvements to syntax and indent files, for one).

Please do not take these questions as criticism. That the maintainers would focus on functionality rather than documentation would feel perfectly understandable, we all have a day job to attend to after all.

None taken. Thanks for the feedback. At the moment, my programming energy is spent at work and on https://github.com/benknoble/frosthaven-manager. But I write all the Racket for the latter project in Vim, so I make occasional improvements to it as I work. Suggestions welcome.

amosnier commented 1 year ago

@benknoble, thanks for the additional information. Please feel free to close. I guess we can archive the issue as properly documented.

Bonne journée.

benknoble commented 1 year ago

À vous aussi 🇫🇷

amosnier commented 1 year ago

Just in case someone would come across this issue, I now think that the whole thing was more about a misconfiguration on my part than anything else. My Vim configuration was built from scratch, which generally is a good thing, but I ended up missing a few very basic sane defaults, and that made my undo functionality very weak. I could basically not undo changes made before write. I believe what has solved that is simply:

if has("vms")
  set nobackup          " do not keep a backup file, use versions instead
else
  set backup            " keep a backup file (restore to previous version)
  if has('persistent_undo')
    set undofile        " keep an undo file (undo changes after closing)
  endif
endif

from https://github.com/vim/vim/blob/master/runtime/vimrc_example.vim.

In any case, with a correct backup/undo configuration, this issue really is a non-issue. Good that it's closed, then...