<commit_before>/*
 * Copyright 2013 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package laika.render

import laika.tree.Elements._

/** API for renderers that produce character output.
 *  
 *  @param out the function to use for writing character data 
 *  @param render the function to use for rendering child elements 
 *  @param indentItem the string to write for a single level of indentation
 *  @param newLine the new line character sequence 
 * 
 *  @author <NAME>
 */
class TextWriter (out: String => Unit, 
                  render: Element => Unit, 
                  indentItem: String = "  ", 
                  newLine: String = "\n") {

  
  protected object Indent {
    
    var current = newLine
    
    def >>> = { current += indentItem; this }
    
    def <<< = { current = current.dropRight(indentItem.length); this }
    
    def write = { out(current); this }
    
    def indented (indent: Int, block: => Unit) = {
      if (indent > (current.length - 1) && indentItem.nonEmpty) {
        val oldIndent = current
        current = "\n" + (" " * indent)
        block
        current = oldIndent
      }
      else block
    }  
    
  }
  
  
  /** Executes the specified block while temporarily
   *  shifting the indentation level (if it is greater
   *  than the currently active one).
   */
  def indented (indent: Int)(block: => Unit) = Indent.indented(indent, block)
  
  /** Writes a new line character sequence.
   */
  def <| : this.type = { Indent.write; this }
  
  
  /** Writes the specified string to the output, on the same line.
   */
  def << (str: String): this.type = { out(str); this }
  
  /** Writes the specified elements to the output, 
   *  all on the same line.
   */
  def << (elements: Seq[Element]): this.type = { elements.foreach(render); this }

  /** Writes the specified element to the output, 
   *  on the same line.
   */
  def << (element: Element): this.type = { render(element); this }
  
  

  /** Writes the specified string to the output, 
   *  on a new line using the current level of indentation.
   */
  def <<| (str: String): this.type = { Indent.write; out(str); this }
  
  /** Writes the specified elements to the output, 
   *  each of them on a new line using the current level of indentation.
   */
  def <<| (elements: Seq[Element]): this.type = { elements.foreach(e => { Indent.write; render(e) }); this }
  
  /** Writes the specified element to the output, 
   *  on a new line using the current level of indentation.
   */
  def <<| (element: Element): this.type = { Indent.write; render(element); this }
  
   
  /** Writes the specified string to the output, 
   *  on a new line and increasing indentation one level to the right.  
   */
  def <<|> (str: String): this.type = {
    Indent.>>>.write
    out(str)
    Indent.<<<.write
    this
  }
  
  /** Writes the specified elements to the output, 
   *  each of them on a new line with the indentation increased one level to the right.
   */
  def <<|> (elements: Seq[Element]): this.type = {
    Indent.>>>
    elements.foreach { e => 
      Indent.write
      render(e)
    }
    Indent.<<<
    this
  }
  
  /** Writes the specified element to the output, 
   *  on a new line and increasing indentation one level to the right.  
   */
  def <<|> (element: Element): this.type = {
    Indent.>>>.write
    render(element)
    Indent.<<<.write
    this
  }
  
  
}
<commit_msg>keep track of parent element stack in TextWriter<commit_after>/*
 * Copyright 2013 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package laika.render

import laika.tree.Elements._

/** API for renderers that produce character output.
 *  
 *  @param out the function to use for writing character data 
 *  @param render the function to use for rendering child elements 
 *  @param indentItem the string to write for a single level of indentation
 *  @param newLine the new line character sequence 
 * 
 *  @author <NAME>
 */
class TextWriter (out: String => Unit, 
                  render: Element => Unit, 
                  indentItem: String = "  ", 
                  newLine: String = "\n") {

  
  protected object Indent {
    
    var current = newLine
    
    def >>> = { current += indentItem; this }
    
    def <<< = { current = current.dropRight(indentItem.length); this }
    
    def write = { out(current); this }
    
    def indented (indent: Int, block: => Unit) = {
      if (indent > (current.length - 1) && indentItem.nonEmpty) {
        val oldIndent = current
        current = "\n" + (" " * indent)
        block
        current = oldIndent
      }
      else block
    }  
    
  }
  
  private var parentStack: List[Element] = Nil
  
  protected def parents = parentStack
  
  private def renderElement (element: Element) = {
    parentStack = element :: parentStack
    render(element)
    parentStack = parentStack.tail
  }
  
  /** Executes the specified block while temporarily
   *  shifting the indentation level (if it is greater
   *  than the currently active one).
   */
  def indented (indent: Int)(block: => Unit) = Indent.indented(indent, block)
  
  /** Writes a new line character sequence.
   */
  def <| : this.type = { Indent.write; this }
  
  
  /** Writes the specified string to the output, on the same line.
   */
  def << (str: String): this.type = { out(str); this }
  
  /** Writes the specified elements to the output, 
   *  all on the same line.
   */
  def << (elements: Seq[Element]): this.type = { elements.foreach(renderElement); this }

  /** Writes the specified element to the output, 
   *  on the same line.
   */
  def << (element: Element): this.type = { renderElement(element); this }
  
  

  /** Writes the specified string to the output, 
   *  on a new line using the current level of indentation.
   */
  def <<| (str: String): this.type = { Indent.write; out(str); this }
  
  /** Writes the specified elements to the output, 
   *  each of them on a new line using the current level of indentation.
   */
  def <<| (elements: Seq[Element]): this.type = { elements.foreach(e => { Indent.write; renderElement(e) }); this }
  
  /** Writes the specified element to the output, 
   *  on a new line using the current level of indentation.
   */
  def <<| (element: Element): this.type = { Indent.write; renderElement(element); this }
  
   
  /** Writes the specified string to the output, 
   *  on a new line and increasing indentation one level to the right.  
   */
  def <<|> (str: String): this.type = {
    Indent.>>>.write
    out(str)
    Indent.<<<.write
    this
  }
  
  /** Writes the specified elements to the output, 
   *  each of them on a new line with the indentation increased one level to the right.
   */
  def <<|> (elements: Seq[Element]): this.type = {
    Indent.>>>
    elements.foreach { e => 
      Indent.write
      renderElement(e)
    }
    Indent.<<<
    this
  }
  
  /** Writes the specified element to the output, 
   *  on a new line and increasing indentation one level to the right.  
   */
  def <<|> (element: Element): this.type = {
    Indent.>>>.write
    renderElement(element)
    Indent.<<<.write
    this
  }
  
  
}

{'fraction_non_alphanumeric': 0.10894564822660695, 'fraction_numerical': 0.002178912964532139, 'mean_word_length': 2.52023860247124, 'pattern_counts': {'":': 0, '<': 67, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6098775', 'n_tokens_mistral': 2455, 'n_tokens_neox': 2389, 'n_words': 913}