summaryrefslogtreecommitdiff
path: root/src/reflect/scala/reflect/internal/util/StringOps.scala
blob: 2fee6b0f82e9b40737034bf4b8c93b140e723f38 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/*                     __                                               *\
**     ________ ___   / /  ___     Scala API                            **
**    / __/ __// _ | / /  / _ |    (c) 2002-2013, LAMP/EPFL             **
**  __\ \/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **
** /____/\___/_/ |_/____/_/ | |                                         **
**                          |/                                          **
\*                                                                      */

package scala
package reflect
package internal
package util

import java.lang.System.{lineSeparator => EOL}

/** This object provides utility methods to extract elements
 *  from Strings.
 *
 *  @author Martin Odersky
 *  @version 1.0
 */
trait StringOps {
  def oempty(xs: String*)        = xs filterNot (x => x == null || x == "")
  def ojoin(xs: String*): String = oempty(xs: _*) mkString " "
  def longestCommonPrefix(xs: List[String]): String = xs match {
    case Nil      => ""
    case w :: Nil => w
    case _        =>
      def lcp(ss: List[String]): String = {
        val w :: ws = ss
        if (w == "") ""
        else if (ws exists (s => s == "" || (s charAt 0) != (w charAt 0))) ""
        else w.substring(0, 1) + lcp(ss map (_ substring 1))
      }
      lcp(xs)
  }
  /** Like String#trim, but trailing whitespace only.
   */
  def trimTrailingSpace(s: String): String = {
    var end = s.length
    while (end > 0 && s.charAt(end - 1).isWhitespace)
      end -= 1

    if (end == s.length) s
    else s.substring(0, end)
  }
  /** Breaks the string into lines and strips each line before reassembling. */
  def trimAllTrailingSpace(s: String): String = s.lines.map(trimTrailingSpace).mkString(EOL)

  def decompose(str: String, sep: Char): List[String] = {
    def ws(start: Int): List[String] =
      if (start == str.length) List()
      else if (str.charAt(start) == sep) ws(start + 1)
      else {
        val end = str.indexOf(sep, start)
        if (end < 0) List(str.substring(start))
        else str.substring(start, end) :: ws(end + 1)
      }
    ws(0)
  }

  def words(str: String): List[String] = decompose(str, ' ')

  def splitWhere(str: String, f: Char => Boolean, doDropIndex: Boolean = false): Option[(String, String)] =
    splitAt(str, str indexWhere f, doDropIndex)

  def splitAt(str: String, idx: Int, doDropIndex: Boolean = false): Option[(String, String)] =
    if (idx == -1) None
    else Some((str take idx, str drop (if (doDropIndex) idx + 1 else idx)))

  /** Returns a string meaning "n elements".
   *  Don't try an element such as "index" with irregular plural.
   */
  def countElementsAsString(n: Int, element: String): String =
    n match {
      case 0 => s"no ${element}s"
      case 1 => s"one ${element}"
      case _ => s"${countAsString(n)} ${element}s"
    }

  /** Turns a count into a friendly English description if n<=4.
   *  Otherwise, a scary math representation.
   */
  def countAsString(n: Int): String =
    n match {
      case 0 => "none"
      case 1 => "one"
      case 2 => "two"
      case 3 => "three"
      case 4 => "four"
      case _ => n.toString
    }
}

object StringOps extends StringOps