Skip to content

feature: allow using in git COMMIT_EDITMSG files #141

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
mikavilpas opened this issue Aug 21, 2024 · 13 comments
Closed

feature: allow using in git COMMIT_EDITMSG files #141

mikavilpas opened this issue Aug 21, 2024 · 13 comments
Labels
enhancement New feature or request

Comments

@mikavilpas
Copy link

Is your feature request related to a problem? Please describe.

Thanks for this awesome plugin! I use it through lazyvim.
I often write my git commit messages in neovim, and fenced code blocks would look nice if they were rendered by this plugin.

Is this possible to configure? I don't have much experience with this.

Describe the solution you'd like

Can we provide some example configuration on how to set this up? I would be fine with maintaining this myself if you would like to keep it out of the plugin repo.

Describe alternatives you've considered

Could also enable this by default, maybe with a config option

Additional information

No response

@mikavilpas mikavilpas added the enhancement New feature or request label Aug 21, 2024
@mikavilpas
Copy link
Author

I can get this plugin to work in COMMIT_EDITMSG files by setting :set ft=markdown but that also starts some markdown related LSP servers which I don't really need when working with commit messages.

@MeanderingProgrammer
Copy link
Owner

MeanderingProgrammer commented Aug 21, 2024

Thank you, I'm glad you're liking it :)

That's a neat idea, I largely write markdown for my own commit messages and don't know why I didn't think to figure this out. It's pretty straightforward, just requires 2 changes and is the same process as adding vimwiki support, plus one extra step due to the LazyVim default configuration.

  1. Add gitcommit to the file_types configuration option of this plugin. I'm not really sure how to modify configurations for plugins configured by LazyVim but just some way to add gitcommit to opts.file_types: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/plugins/extras/lang/markdown.lua#L97

    opts = {
        file_types = { 'markdown', 'norg', 'rmd', 'org', 'gitcommit' },
    }
  2. Register markdown as the parser for gitcommit files. This can be done anywhere in your config so long as it runs before this plugin tries to render a file.

    vim.treesitter.language.register('markdown', 'gitcommit')
  3. This is the extra step that's LazyVim specific, by default the plugin is set to lazy load on the same file types as provided in opts. You'll need to do a similar change and add gitcommit to ft: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/plugins/extras/lang/markdown.lua#L108

    ft =  { 'markdown', 'norg', 'rmd', 'org', 'gitcommit' },

Since we're not modifying the file type to accomplish this it should avoid starting any markdown related LSP servers, though I did not double check this.

I ended up making this change for my own config: MeanderingProgrammer/dotfiles@680bc0a

A couple of other minor things to consider:

  • If you have the gitcommit treesitter parser installed it would probably be a good idea to remove it, since we've registered markdown as the parser it should be unused
  • Commit messages do not follow markdown syntax, I believe any invalid syntax will essentially be skipped over and this plugin should render anything that looks like markdown but it won't be perfect

Note

In case you're wondering why are there 2 identical lists?

ft is for lazy.nvim to determine when to lazy load this plugin.
If lazy.nvim didn't have the list it would load this plugin on startup. I personally don't recommend lazy loading this plugin because of this redundancy and the relatively low startup time of this plugin, but it's not really a problem.

opts.file_types is for this plugin, once loaded, to know what files to run on.
If this plugin didn't have a list of file types it would try to run on every file after it is loaded, which would add a lot of overhead since this plugin attaches many event listeners to these buffers.

Since sharing information between a plugin and plugin manager is in no way standardized there's not really a way to have it only defined in one place, other than using a local variable in your config of course.

@MeanderingProgrammer
Copy link
Owner

In case you want to set different configuration values for commit files I pushed a change to allow overrides based on filetype here: 952b1c0.

So to disable headings in gitcommit files (just as an example) you would do:

opts = {
    ...
    overrides = {
        filetype = {
            gitcommit = { heading = { enabled = false } },
        },
    },
}

@mikavilpas
Copy link
Author

Wow this solution is incredible! Huge thanks.

image

mikavilpas/dotfiles@ed18a16

In my image you can see the full diff at the bottom - it's there for github copilot to get some context when suggesting what to write in the commit message. I never read it and don't really care if it's not highlighted 🙂

@MeanderingProgrammer
Copy link
Owner

Sweet, no problem :)

I looked at your change and removing the heading isn't strictly necessary, though likely a good idea if you use the default # comment character. You can also change it to something else, I use ;, in your git config:

[core]
    commentChar = ";"

Then re-enable headings.

Huh, I've not seen the putting the diff in the commit approach before, make sense. Depending on how that diff gets there if you have any control over it, surrounding it with a code block using the diff language will make it look nicer:

```diff
<contents_of_diff>
```

Assuming you have the diff parser installed.

@mikavilpas
Copy link
Author

I didn't know core.commentChar exists. This is very nice - now even headings work :)

I'm sure the diff highlighting could be made to work with a prepare-commit-msg git hook, but I think it would be better to somehow get the markdown and gitcommit treesitter parsers to work together.

I might look into this later, I should learn a bit more about how the parsers work.

@MeanderingProgrammer
Copy link
Owner

MeanderingProgrammer commented Aug 27, 2024

I got a version of this that's almost perfect, however doesn't support the custom core.commentChar, so you'll need to remove that for this to work. Naturally that means headings won't work either.

Instead of parsing the entire commit as markdown using: vim.treesitter.language.register('markdown', 'gitcommit'), we can inject markdown into the message body. So remove that line from the config.

Then install the gitcommit parser: :TSInstall gitcommit.

Finally extending the gitcommit injections to parse the message body only as markdown. To do this add a file named after/queries/gitcommit/injections.scm with the following content:

;extends

((message) @injection.content
  (#set! injection.combined)
  (#set! injection.include-children)
  (#set! injection.language "markdown"))

This will use the parser to highlight the main commit message, comments and diff with --verbose nicely, as well as triggering this plugin to handle the main message body.

The core.commentChar limitation comes from the gitcommit parser itself since it finds comments based on the hard coded # default, there's an issue open for this: gbprod/tree-sitter-gitcommit#45.

Even with a custom core.commentChar it doesn't look worse so I changed to this approach myself: MeanderingProgrammer/dotfiles@17d396e

@mikavilpas
Copy link
Author

Wow this solution is amazing! For now I think I can work around the limitations of core.commentChar by using === under headings (the alternate markdown heading syntax.

I think this is a really cool feature. Have you thought about including it in the plugin?

@MeanderingProgrammer
Copy link
Owner

MeanderingProgrammer commented Aug 27, 2024

Do you mean adding details about enabling the plugin for commit messages or support for the alternate markdown heading syntax?

@mikavilpas
Copy link
Author

I mean, is it possible to simplify the setup for using render-markdown.nvim in gitcommit buffers, and make it a more "batteries included" experience within render-markdown.nvim for example?

To be honest, I don't know if plugins can add treesitter injections. I feel like this is one of those "it's clearly better to have this" features, and got a bit excited. 😄

@MeanderingProgrammer
Copy link
Owner

Ah, gotcha. I'll look into it and see. Similarly I have no idea if a plugin can define injections programatically. Worst case I'll add some documentation, best case I can add some default injections based on filetype and allow users to opt out and define their own.

MeanderingProgrammer added a commit that referenced this issue Aug 28, 2024
## Details

Discussed here: #141

When using this plugin with multiple filetypes it would be nice if the
tree-sitter injection logic could be offloaded from the user and be
handled by the plugin. Especially when the way markdown would be
injected is likely to be the same for anyone that wants the plugin to
work within the filetype.

Turns out this is fairly straightforward using the
vim.treesitter.query.set API, and specifying the injections query name.
The only slight complication is that in order to be able to extend the
existing injections (instead of overwriting them) we need a way to get
the current injection query as a string. The only way I found to do that
is to pull the files associated with injections then read and append
them together. All other ways to get the query return different kinds of
objects that would need to be serialized back into a string.

I have made this part of the configuration users can modify with the top
level `injections` field. Currently a value is only specified for the
gitcommit filetype. Injections are only processed if this plugin is
meant to run on that filetype, meaning additional configurations can be
added without impacting users who do not use this plugin on multiple
file types.

Users are free to:

- modify the queries used
- disable the injection, by setting enabled to false
- add entirely new queries that are coupled to this plugin rather than needing to
  live in their global queries configuration
@MeanderingProgrammer
Copy link
Owner

I've implemented a batteries included approach here: 5ff9a59

Takes care of setting injections using vim.treesitter.query.set, completely configurable on the user side with a default for gitcommit. Currently the only one, will expand it as things come up.

With this you can remove the after/queries/gitcommit/injections.scm file. So now the only things that are needed are the gitcommit treesitter parser and adding gitcommit to the plugin file_types config.

Since this does happen as part of the plugin's configuration lazy loading the plugin could cause problems in that the injection will be added after the buffer loads. So if it doesn't work I would suggest disabling lazy loading and giving that a try.

Thanks for the suggestion, I personally like it as well!

@mikavilpas
Copy link
Author

I can confirm it works nicely. 👍🏻 No issues with lazy loading have come up either.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants