internal/commentpolicy/gen/main.go
1
// Command gen renders the language reference from the syntax table that
2
// decides it, so the page cannot describe a filetype koment does not detect.
3
package main
5
import (
6
"bytes"
7
"flag"
8
"fmt"
9
"os"
10
"strings"
12
"github.com/koment-dev/koment/internal/commentpolicy"
13
)
15
func main() {
16
destination := flag.String("out", "", "path of the reference page to write")
17
flag.Parse()
19
if *destination == "" {
20
fmt.Fprintln(os.Stderr, "gen: -out is required")
21
os.Exit(2)
22
}
23
if err := os.WriteFile(*destination, reference(), 0o600); err != nil {
24
fmt.Fprintf(os.Stderr, "gen: writing %s: %v\n", *destination, err)
25
os.Exit(1)
26
}
27
}
29
func reference() []byte {
30
page := &bytes.Buffer{}
32
fmt.Fprint(page, `# Language support
34
<!-- Generated by internal/commentpolicy/gen. Edit the syntax table, not this page. -->
36
koment does two different things to a file, and they have different reach.
38
**Anchoring** binds an annotation to a snippet of text. It is a verbatim search
39
with surrounding context, so it has no idea what language it is looking at and
40
works in every file in the repository.
42
**Comment detection** finds the comments already in a file so koment can flag
43
them, convert them, or offer to. It has to know where a comment ends and a
44
string begins, so it reads the file's syntax.
46
Everything below is about the second one.
48
## Which detector reads a file
50
`, "")
52
fmt.Fprintf(page, "| detector | files | what it knows |\n|---|---|---|\n")
53
fmt.Fprintf(page, "| `%s` | `*.go` | comment groups, and godoc on exported identifiers |\n",
54
commentpolicy.DetectorName("main.go"))
55
fmt.Fprintf(page, "| `%s` | everything else | the line and block markers listed below |\n\n",
56
commentpolicy.DetectorName("config.yaml"))
58
fmt.Fprintf(page, `The Go parser is tried first, because no marker scan can tell godoc on an
59
exported identifier from ordinary prose.
61
## What detection gives you
63
- `+"`koment comments check`"+` — the gate that fails when a prohibited comment lands
64
- `+"`koment comments convert`"+` — move a comment into an annotation and delete it
65
- `+"`koment comments acknowledge`"+` — keep a comment, attributably
66
- the editor prompt that offers to convert a comment as you finish typing it
68
These work in every filetype below. Only the formats in
69
[Never scanned](#never-scanned) report `+"`no comment detector for <file>`"+`.
71
## Filetypes the scan names
73
A **directive** is a prefix koment passes through untouched, because the
74
toolchain requires it rather than a person explaining something.
76
| extension | line | block | directives |
77
|---|---|---|---|
78
`)
80
for _, filetype := range commentpolicy.DetectedFiletypes() {
81
fmt.Fprintf(page, "| `%s` | %s | %s | %s |\n",
82
filetype.Extension,
83
code(filetype.Line),
84
blocks(filetype.Block),
85
code(filetype.Directives),
86
)
87
}
89
fmt.Fprintf(page, `
90
## Anything else
92
An extension this page does not name is still scanned, using %s.
94
`, code(commentpolicy.FallbackMarkers()))
96
fmt.Fprintf(page, "`--` is deliberately absent from that fallback: it opens a comment in Lua, "+
97
"SQL and Haskell, which declare it above, and separates YAML documents everywhere else.\n\n")
99
fmt.Fprintf(page, "These extensionless filenames are read as shell:\n\n%s\n\n",
100
code(commentpolicy.ScriptFilenames()))
102
fmt.Fprintf(page, "So is any dotfile whose name carries no further extension — `.gitignore`, `.editorconfig`.\n\n")
104
fmt.Fprintf(page, "## Never scanned\n\nProse and data formats carry no comment syntax to find, and scanning them "+
105
"would read every Markdown heading as a violation:\n\n%s\n\nAnnotate them freely; anchoring does not care.\n",
106
code(commentpolicy.UndetectedExtensions()))
108
return page.Bytes()
109
}
111
func code(values []string) string {
112
if len(values) == 0 {
113
return "—"
114
}
115
quoted := make([]string, 0, len(values))
116
for _, value := range values {
117
quoted = append(quoted, "`"+value+"`")
118
}
119
return strings.Join(quoted, " ")
120
}
122
func blocks(delimiters []commentpolicy.BlockDelimiter) string {
123
if len(delimiters) == 0 {
124
return "—"
125
}
126
rendered := make([]string, 0, len(delimiters))
127
for _, delimiter := range delimiters {
128
rendered = append(rendered, "`"+delimiter.Open+" … "+delimiter.Close+"`")
129
}
130
return strings.Join(rendered, " ")
131
}