https://github.com/matttproud/gofencefmt
Binary gofencefmt reformats Go code that appears in Markdown code fences.
https://github.com/matttproud/gofencefmt
go markdown nvim vim
Last synced: 2 months ago
JSON representation
Binary gofencefmt reformats Go code that appears in Markdown code fences.
- Host: GitHub
- URL: https://github.com/matttproud/gofencefmt
- Owner: matttproud
- License: apache-2.0
- Created: 2025-09-03T20:32:10.000Z (10 months ago)
- Default Branch: main
- Last Pushed: 2025-10-23T10:26:11.000Z (8 months ago)
- Last Synced: 2025-12-10T18:52:39.433Z (7 months ago)
- Topics: go, markdown, nvim, vim
- Language: Go
- Homepage:
- Size: 24.4 KB
- Stars: 1
- Watchers: 0
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# gofencefmt
gofencefmt is a tool to reformat blocks of Go code (in the spirit of `gofmt`)
that appear in a Markdown code fence.
## Motivating Examples
Let's consider some examples:
In the simplest case, we have a code snippet that is not indented correctly.
```go
// Input:
package main
func songThatNeverEnds() {
itGoesOn()
andOn()
myFriends()
}
```
If you run gofencefmt on the fence's contents, it will produce this:
```go
// Output:
package main
func songThatNeverEnds() {
itGoesOn()
andOn()
myFriends()
}
```
Note that the code is indented even with Go's native tabs. Now, that isn't all
that interesting in and of itself, so let's consider some more interesting
cases:
1. **Indented Fences**: Below we have an indented code fence that is a child
of this Markdown list item. It's also malformatted.
```go
// Input:
package main
func songThatNeverEnds() {
itGoesOn()
andOn()
myFriends()
}
```
When gofencefmt is run on the literal text range of the indented fence, it
ensures the output matches the same fundamental level of Markdown
indentation.
```go
// Output:
package main
func songThatNeverEnds() {
itGoesOn()
andOn()
myFriends()
}
```
2. **Supports Snippet**: Sometimes when writing code snippets, we like to excerpt
top-level identifiers without them being part of a whole program.
```go
// Input:
func songThatNeverEnds() {
itGoesOn()
andOn()
myFriends()
}
```
gofencefmt handles these just fine:
```go
// Output:
func songThatNeverEnds() {
itGoesOn()
andOn()
myFriends()
}
```
**Note:** There is no `package` clause in the snippet above!
gofencefmt can even do this for code snippets that would appear inline in a
function (or method).
```go
// Input:
for isSongThatNeverEnds() {
itGoesOn()
andOn()
myFriends()
}
```
And even output them in the most concise and indentation-correct way:
```go
// Output:
for isSongThatNeverEnds() {
itGoesOn()
andOn()
myFriends()
}
```
## Installation
Use the standard `go install` workflow as follows:
```shell
% go install github.com/matttproud/gofencefmt@latest
```
## Usage
I have been using this with Vim and Neovim through the `!` program filter
directive. I use visual line mode to select the range of interest, which is
exclusively the Go code in the code fence, and enter the command `:!
gofencefmt`.
Let's imagine Vim open as such:
````
```go {.good}
VL func Test(t *testing.T) {
VL // elided
VL if diff := cmp.Diff(want, got); diff != "" {
VL t.Errorf("f() = %v, want %v diff (-want, got):\n\n%v", got, want, diff)
VL }
VL // elided
VL }
```
````
Here the lines prefixed with "VL" indicate these lines have been selected in
visual line mode (**Note:** "VL" is an annotation I am providing, nothing you
will see in Vim). After the visual selection has been made, run
`:! gofencefmt`.
I have **not** tested this gofencefmt with [`conform.nvim`]'s [injected
language formatting]. I presume it would work in some capacity.
[`conform.nvim`]: https://github.com/stevearc/conform.nvim
[injected language formatting]: https://github.com/stevearc/conform.nvim/blob/master/doc/advanced_topics.md#injected-language-formatting-code-blocks