1# Copyright 2017 Google LLC 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15# snipdoc merges code snippets from Go source files into a template to 16# produce another go file (typically doc.go). 17# 18# Call with one or more .go files and a template file. 19# 20# awk -f snipmd.awk foo.go bar.go doc.template 21# 22# In the Go files, start a snippet with 23# //[ NAME 24# and end it with 25# //] 26# 27# In the template, write 28# [NAME] 29# on a line by itself to insert the snippet NAME on that line. 30# 31# The following transformations are made to the Go code: 32# - Trailing blank lines are removed. 33# - `ELLIPSIS` and `_ = ELLIPSIS` are replaced by `...` 34 35 36/^[ \t]*\/\/\[/ { # start snippet in Go file 37 if (inGo()) { 38 if ($2 == "") { 39 die("missing snippet name") 40 } 41 curSnip = $2 42 next 43 } 44} 45 46/^[ \t]*\/\/]/ { # end snippet in Go file 47 if (inGo()) { 48 if (curSnip != "") { 49 # Remove all trailing newlines. 50 gsub(/[\t\n]+$/, "", snips[curSnip]) 51 curSnip = "" 52 next 53 } else { 54 die("//] without corresponding //[") 55 } 56 } 57} 58 59ENDFILE { 60 if (curSnip != "") { 61 die("unclosed snippet: " curSnip) 62 } 63} 64 65/^\[.*\]$/ { # Snippet marker in template file. 66 if (inTemplate()) { 67 name = substr($1, 2, length($1)-2) 68 if (snips[name] == "") { 69 die("no snippet named " name) 70 } 71 printf("%s\n", snips[name]) 72 afterSnip = 1 73 next 74 } 75} 76 77# Matches every line. 78{ 79 if (curSnip != "") { 80 # If the first line in the snip has no indent, add the indent. 81 if (snips[curSnip] == "") { 82 if (index($0, "\t") == 1) { 83 extraIndent = "" 84 } else { 85 extraIndent = "\t" 86 } 87 } 88 89 line = $0 90 # Replace ELLIPSIS. 91 gsub(/_ = ELLIPSIS/, "...", line) 92 gsub(/ELLIPSIS/, "...", line) 93 94 snips[curSnip] = snips[curSnip] extraIndent line "\n" 95 } else if (inTemplate()) { 96 afterSnip = 0 97 # Copy to output. 98 print 99 } 100} 101 102 103 104function inTemplate() { 105 return match(FILENAME, /\.template$/) 106} 107 108function inGo() { 109 return match(FILENAME, /\.go$/) 110} 111 112 113function die(msg) { 114 printf("%s:%d: %s\n", FILENAME, FNR, msg) > "/dev/stderr" 115 exit 1 116} 117