transform.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*
  2. * Public Domain Software
  3. *
  4. * I (Matthias Ladkau) am the author of the source code in this file.
  5. * I have placed the source code in this file in the public domain.
  6. *
  7. * For further information see: http://creativecommons.org/publicdomain/zero/1.0/
  8. */
  9. package stringutil
  10. import (
  11. "bufio"
  12. "bytes"
  13. "io"
  14. "math"
  15. "regexp"
  16. "strings"
  17. "unicode"
  18. )
  19. var cSyleCommentsRegexp = regexp.MustCompile("(?s)//.*?\n|/\\*.*?\\*/")
  20. /*
  21. StripCStyleComments strips out C-Style comments from a given string.
  22. */
  23. func StripCStyleComments(text []byte) []byte {
  24. return cSyleCommentsRegexp.ReplaceAll(text, nil)
  25. }
  26. /*
  27. CreateDisplayString changes all "_" characters into spaces and properly capitalizes
  28. the resulting string.
  29. */
  30. func CreateDisplayString(str string) string {
  31. if len(str) == 0 {
  32. return ""
  33. }
  34. return ProperTitle(strings.Replace(str, "_", " ", -1))
  35. }
  36. // The following words should not be capitalized
  37. //
  38. var notCapitalize = map[string]string{
  39. "a": "",
  40. "an": "",
  41. "and": "",
  42. "at": "",
  43. "but": "",
  44. "by": "",
  45. "for": "",
  46. "from": "",
  47. "in": "",
  48. "nor": "",
  49. "on": "",
  50. "of": "",
  51. "or": "",
  52. "the": "",
  53. "to": "",
  54. "with": "",
  55. }
  56. /*
  57. ProperTitle will properly capitalize a title string by capitalizing the first, last
  58. and any important words. Not capitalized are articles: a, an, the; coordinating
  59. conjunctions: and, but, or, for, nor; prepositions (fewer than five
  60. letters): on, at, to, from, by.
  61. */
  62. func ProperTitle(input string) string {
  63. words := strings.Fields(strings.ToLower(input))
  64. size := len(words)
  65. for index, word := range words {
  66. if _, ok := notCapitalize[word]; !ok || index == 0 || index == size-1 {
  67. words[index] = strings.Title(word)
  68. }
  69. }
  70. return strings.Join(words, " ")
  71. }
  72. /*
  73. ToUnixNewlines converts all newlines in a given string to unix newlines.
  74. */
  75. func ToUnixNewlines(s string) string {
  76. s = strings.Replace(s, "\r\n", "\n", -1)
  77. return strings.Replace(s, "\r", "\n", -1)
  78. }
  79. /*
  80. TrimBlankLines removes blank initial and trailing lines.
  81. */
  82. func TrimBlankLines(s string) string {
  83. return strings.Trim(s, "\r\n")
  84. }
  85. /*
  86. StripUniformIndentation removes uniform indentation from a string.
  87. */
  88. func StripUniformIndentation(s string) string {
  89. leadingWhitespace := func(line string) int {
  90. var count int
  91. // Count leading whitespaces in a string
  92. for _, r := range line {
  93. if unicode.IsSpace(r) || unicode.IsControl(r) {
  94. count++
  95. } else {
  96. return count
  97. }
  98. }
  99. return -1 // Special case line is full of whitespace
  100. }
  101. // Count the minimum number of leading whitespace excluding
  102. // empty lines
  103. minCount := math.MaxInt16
  104. reader := strings.NewReader(s)
  105. scanner := bufio.NewScanner(reader)
  106. for scanner.Scan() {
  107. if lw := leadingWhitespace(scanner.Text()); lw != -1 {
  108. if lw < minCount {
  109. minCount = lw
  110. }
  111. }
  112. }
  113. // Go through the string again and build up the output
  114. var buf bytes.Buffer
  115. reader.Seek(0, io.SeekStart)
  116. scanner = bufio.NewScanner(reader)
  117. for scanner.Scan() {
  118. line := scanner.Text()
  119. if strings.TrimSpace(line) != "" {
  120. for i, r := range line {
  121. if i >= minCount {
  122. buf.WriteRune(r)
  123. }
  124. }
  125. }
  126. buf.WriteString("\n")
  127. }
  128. // Prepare output string
  129. ret := buf.String()
  130. if !strings.HasSuffix(s, "\n") {
  131. ret = ret[:len(ret)-1]
  132. }
  133. return ret
  134. }