bitbucket.org/ai69/amoy@v0.2.3/heredoc.go (about)

     1  package amoy
     2  
     3  // Migrate from https://github.com/makenowjust/heredoc/blob/main/heredoc.go
     4  
     5  import (
     6  	"fmt"
     7  	"strings"
     8  )
     9  
    10  // HereDoc returns un-indented string as here-document.
    11  func HereDoc(raw string) string {
    12  	skipFirstLine := false
    13  	if len(raw) > 0 && raw[0] == '\n' {
    14  		raw = raw[1:]
    15  	} else {
    16  		skipFirstLine = true
    17  	}
    18  
    19  	rawLines := strings.Split(raw, "\n")
    20  	lines := rawLines
    21  	if skipFirstLine {
    22  		lines = lines[1:]
    23  	}
    24  
    25  	minIndentSize := getMinIndent(lines)
    26  	lines = removeIndentation(lines, minIndentSize)
    27  
    28  	return strings.Join(rawLines, "\n")
    29  }
    30  
    31  // isSpace checks whether the rune represents space or not.
    32  // Only white spcaes (U+0020) and horizontal tabs are treated as space character.
    33  // It is the same as Go.
    34  //
    35  // See https://github.com/MakeNowJust/heredoc/issues/6#issuecomment-524231625.
    36  func isSpace(r rune) bool {
    37  	switch r {
    38  	case ' ', '\t':
    39  		return true
    40  	default:
    41  		return false
    42  	}
    43  }
    44  
    45  // getMinIndent calculates the minimum indentation in lines, excluding empty lines.
    46  func getMinIndent(lines []string) int {
    47  	minIndentSize := MaxInt
    48  
    49  	for i, line := range lines {
    50  		indentSize := 0
    51  		for _, r := range line {
    52  			if isSpace(r) {
    53  				indentSize++
    54  			} else {
    55  				break
    56  			}
    57  		}
    58  
    59  		if len(line) == indentSize {
    60  			if i == len(lines)-1 && indentSize < minIndentSize {
    61  				lines[i] = ""
    62  			}
    63  		} else if indentSize < minIndentSize {
    64  			minIndentSize = indentSize
    65  		}
    66  	}
    67  	return minIndentSize
    68  }
    69  
    70  // removeIndentation removes n characters from the front of each line in lines.
    71  func removeIndentation(lines []string, n int) []string {
    72  	for i, line := range lines {
    73  		if len(lines[i]) >= n {
    74  			lines[i] = line[n:]
    75  		}
    76  	}
    77  	return lines
    78  }
    79  
    80  // HereDocf returns unindented and formatted string as here-document.
    81  // Formatting is done as for fmt.Printf().
    82  func HereDocf(raw string, args ...interface{}) string {
    83  	return fmt.Sprintf(HereDoc(raw), args...)
    84  }