# Copyright 2017 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # snipdoc merges code snippets from Go source files into a template to # produce another go file (typically doc.go). # # Call with one or more .go files and a template file. # # awk -f snipmd.awk foo.go bar.go doc.template # # In the Go files, start a snippet with # //[ NAME # and end it with # //] # # In the template, write # [NAME] # on a line by itself to insert the snippet NAME on that line. # # The following transformations are made to the Go code: # - Trailing blank lines are removed. # - `ELLIPSIS` and `_ = ELLIPSIS` are replaced by `...` /^[ \t]*\/\/\[/ { # start snippet in Go file if (inGo()) { if ($2 == "") { die("missing snippet name") } curSnip = $2 next } } /^[ \t]*\/\/]/ { # end snippet in Go file if (inGo()) { if (curSnip != "") { # Remove all trailing newlines. gsub(/[\t\n]+$/, "", snips[curSnip]) curSnip = "" next } else { die("//] without corresponding //[") } } } ENDFILE { if (curSnip != "") { die("unclosed snippet: " curSnip) } } /^\[.*\]$/ { # Snippet marker in template file. if (inTemplate()) { name = substr($1, 2, length($1)-2) if (snips[name] == "") { die("no snippet named " name) } printf("%s\n", snips[name]) afterSnip = 1 next } } # Matches every line. { if (curSnip != "") { # If the first line in the snip has no indent, add the indent. if (snips[curSnip] == "") { if (index($0, "\t") == 1) { extraIndent = "" } else { extraIndent = "\t" } } line = $0 # Replace ELLIPSIS. gsub(/_ = ELLIPSIS/, "...", line) gsub(/ELLIPSIS/, "...", line) snips[curSnip] = snips[curSnip] extraIndent line "\n" } else if (inTemplate()) { afterSnip = 0 # Copy to output. print } } function inTemplate() { return match(FILENAME, /\.template$/) } function inGo() { return match(FILENAME, /\.go$/) } function die(msg) { printf("%s:%d: %s\n", FILENAME, FNR, msg) > "/dev/stderr" exit 1 }