All Downloads are FREE. Search and download functionalities are using the official Maven repository.

.circumflex-md.2.0.RC2.source-code.util.scala Maven / Gradle / Ivy

The newest version!
package ru.circumflex.md

import java.lang.StringBuilder
import java.util.regex.{Pattern, Matcher}
import Markdown._

/*!# Character protector

We use character protector mechanism to ensure that certain elements of markup,
such as inline HTML blocks, remain undamaged when processing.
*/
class Protector {
  protected var protectHash: Map[String, CharSequence] = Map()
  protected var unprotectHash: Map[CharSequence, String] = Map()

  /**
   * Generates a random hash key.
   */
  def randomKey = (0 to keySize).foldLeft("")((s, i) =>
    s + chars.charAt(rnd.nextInt(keySize)))

  /**
   * Adds the specified token to hash and returns the protection key.
   */
  def addToken(t: CharSequence): String = unprotectHash.get(t) match {
    case Some(key) => key
    case _ =>
      val key = randomKey
      protectHash += key -> t
      unprotectHash += t -> key
      key
  }

  /**
   * Attempts to retrieve an encoded sequence by specified `key`.
   */
  def decode(key: String): Option[CharSequence] = protectHash.get(key)

  /**
   * Returns hash keys that are currently in use.
   */
  def keys = protectHash.keys

  override def toString = protectHash.toString
}

/**
 * Represents a simple wrapper over `StringBuilder` with utility methods.
 */
class StringEx(protected var text: StringBuilder) {

  def this(source: CharSequence) = this(new StringBuilder(source))

  /**
   * Creates a `Matcher` using specified `Pattern` and applies replacements literally
   * (without interpreting $1, $2, etc.) by calling specified `replacementFunction`
   * on each match.
   */
  def replaceAll(pattern: Pattern, replacementFunction: Matcher => CharSequence): this.type = {
    var lastIndex = 0;
    val m = pattern.matcher(text);
    val sb = new StringBuilder();
    while (m.find()) {
      sb.append(text.subSequence(lastIndex, m.start))
      sb.append(replacementFunction(m))
      lastIndex = m.end
    }
    sb.append(text.subSequence(lastIndex, text.length))
    text = sb;
    return this
  }

  /**
   * Replaces all occurences of specified `string` with specified `replacement`
   * without using regular expressions.
   */
  def replaceAll(string: String, replacement: CharSequence): this.type = {
    val result = new StringBuilder
    var startIdx = 0
    var oldIdx = 0
    oldIdx = text.indexOf(string, startIdx)
    while (oldIdx >= 0) {
      result.append(text.substring(startIdx, oldIdx))
      result.append(replacement)
      startIdx = oldIdx + string.length
      oldIdx = text.indexOf(string, startIdx)
    }
    result.append(text.substring(startIdx))
    text = result
    return this
  }

  def replaceAll(pattern: Pattern, replacement: CharSequence, literally: Boolean = true): this.type =
    if (literally) replaceAll(pattern, m => replacement)
    else {
      text = new StringBuilder(pattern.matcher(text).replaceAll(replacement.toString))
      return this
    }

  /**
   * Appends the specified character sequence.
   */
  def append(s: CharSequence): this.type = {
    text.append(s)
    return this
  }

  /**
   * Prepends the specified character sequence.
   */
  def prepend(s: CharSequence): this.type = {
    text = new StringBuilder(s).append(text)
    return this
  }

  /**
   * Removes at most 4 leading spaces at the beginning of every line.
   */
  def outdent(): this.type = replaceAll(rOutdent, "")

  /**
   * Provides the length of the underlying buffer.
   */
  def length = text.length

  /**
   * Extracts the sub-sequence from underlying buffer.
   */
  def subSequence(start: Int, end: Int) =
    text.subSequence(start, end)

  /**
   * Creates a `Matcher` from specified `pattern`.
   */
  def matcher(pattern: Pattern) = pattern.matcher(text)

  /**
   * Emits the content of underlying buffer.
   */
  override def toString = text.toString
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy