dedent.go 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. package dedent
  2. import (
  3. "regexp"
  4. "strings"
  5. )
  6. var (
  7. whitespaceOnly = regexp.MustCompile("(?m)^[ \t]+$")
  8. leadingWhitespace = regexp.MustCompile("(?m)(^[ \t]*)(?:[^ \t\n])")
  9. )
  10. // Dedent removes any common leading whitespace from every line in text.
  11. //
  12. // This can be used to make multiline strings to line up with the left edge of
  13. // the display, while still presenting them in the source code in indented
  14. // form.
  15. func Dedent(text string) string {
  16. var margin string
  17. text = whitespaceOnly.ReplaceAllString(text, "")
  18. indents := leadingWhitespace.FindAllStringSubmatch(text, -1)
  19. // Look for the longest leading string of spaces and tabs common to all
  20. // lines.
  21. for i, indent := range indents {
  22. if i == 0 {
  23. margin = indent[1]
  24. } else if strings.HasPrefix(indent[1], margin) {
  25. // Current line more deeply indented than previous winner:
  26. // no change (previous winner is still on top).
  27. continue
  28. } else if strings.HasPrefix(margin, indent[1]) {
  29. // Current line consistent with and no deeper than previous winner:
  30. // it's the new winner.
  31. margin = indent[1]
  32. } else {
  33. // Current line and previous winner have no common whitespace:
  34. // there is no margin.
  35. margin = ""
  36. break
  37. }
  38. }
  39. if margin != "" {
  40. text = regexp.MustCompile("(?m)^"+margin).ReplaceAllString(text, "")
  41. }
  42. return text
  43. }