snapshot of c000b74a5b09c433f96a69fa102c5c8f6583dff0 Annotations about the code that implements koment.

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
4
5 import (
6 "bytes"
7 "flag"
8 "fmt"
9 "os"
10 "strings"
11
12 "github.com/koment-dev/koment/internal/commentpolicy"
13 )
14
15 func main() {
16 destination := flag.String("out", "", "path of the reference page to write")
17 flag.Parse()
18
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 }
28
29 func reference() []byte {
30 page := &bytes.Buffer{}
31
32 fmt.Fprint(page, `# Language support
33
34 <!-- Generated by internal/commentpolicy/gen. Edit the syntax table, not this page. -->
35
36 koment does two different things to a file, and they have different reach.
37
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.
41
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.
45
46 Everything below is about the second one.
47
48 ## Which detector reads a file
49
50 `, "")
51
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"))
57
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.
60
61 ## What detection gives you
62
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
67
68 These work in every filetype below. Only the formats in
69 [Never scanned](#never-scanned) report `+"`no comment detector for <file>`"+`.
70
71 ## Filetypes the scan names
72
73 A **directive** is a prefix koment passes through untouched, because the
74 toolchain requires it rather than a person explaining something.
75
76 | extension | line | block | directives |
77 |---|---|---|---|
78 `)
79
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 }
88
89 fmt.Fprintf(page, `
90 ## Anything else
91
92 An extension this page does not name is still scanned, using %s.
93
94 `, code(commentpolicy.FallbackMarkers()))
95
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")
98
99 fmt.Fprintf(page, "These extensionless filenames are read as shell:\n\n%s\n\n",
100 code(commentpolicy.ScriptFilenames()))
101
102 fmt.Fprintf(page, "So is any dotfile whose name carries no further extension — `.gitignore`, `.editorconfig`.\n\n")
103
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()))
107
108 return page.Bytes()
109 }
110
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 }
121
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 }

Find an annotation

Search file paths, rationale, kinds, and authors.

moveEnter openEsc close