<commit_before>package latis.writer

import latis.dm._
import java.io.OutputStream
import java.io.PrintWriter

class AsciiWriter extends TextWriter {
  //TODO: rename ModelWriter?
  
  override def makeHeader(dataset: Dataset) = dataset.toString + newLine
  
  def makeScalar(scalar: Scalar): String = scalar match {
    case Index(i) => i.toString
    case Real(d) => d.toString
    case Integer(l) => l.toString
    case Text(s) => s.trim
    case Binary(b) => "blob" //TODO: uuencode?
    //TODO: use Scalar.toStringValue?
  //TODO: deal with Time format
  }
    
  def makeTuple(tuple: Tuple): String = tuple match {
    case Sample(d, r) => varToString(d) + " -> " + varToString(r)
    case Tuple(vars) => vars.map(varToString(_)).mkString("(", ",", ")")
  }
  
  def makeFunction(function: Function): String = function.iterator.map(varToString(_)).mkString(newLine)

    
//  def writeVariable(variable: Variable): Unit = variable match {
//    //TODO: build string instead of writing directly? push into super class
//    
//    case Index(i)   => writer.print(i.toString)
//    case Real(d)    => writer.print(d.toString)
//    case Integer(l) => writer.print(l.toString)
//    case Text(s)    => writer.print(s)
//    case Binary(b)  => writer.print(b) //TODO: uuencode?
//    
//    case Tuple(vars) => {
//      //surround Tuple's Variables with parens
//      writer.print("(")
//      //write each Variable contained in this Tuple separated by commas
//      var first = true
//      for (v <- vars) {
//        if (!first) writer.print(",")
//        else first = false
//        writeVariable(v) //recursive
//      }
//      //close parens
//      writer.print(")")
//    }
//    
//    case f: Function => {
//      writer.println()
//      //TODO: "[]" brackets?
//      for (Sample(domain, range) <- f.iterator) {
//        writeVariable(domain)
//        writer.print(" -> ")
//        writeVariable(range)
//        writer.println()
//      }
//    }
//  }

  /**
   * Note, don't close 'out' because it was given to us.
   * TODO: does this violate some principal? 
   *   consider java.io decorator pattern: does closing decorator close decoratee? 
   *   dangerous side effect? 
   *   use case: out from servet response, what happens if we close it here?
   */
  //def close() {}

}

object AsciiWriter {
  
  def apply(out: OutputStream): AsciiWriter = {
    val writer = new AsciiWriter()
    writer._out = out
    writer
  }
  
  def apply(): AsciiWriter = AsciiWriter(System.out)
  
  def write(dataset: Dataset) = AsciiWriter().write(dataset)
}<commit_msg>add indent to make nested functions look better<commit_after>package latis.writer

import latis.dm._
import java.io.OutputStream
import java.io.PrintWriter

class AsciiWriter extends TextWriter {
  //TODO: rename ModelWriter?
  
  private var indent = 0
  
  override def makeHeader(dataset: Dataset) = dataset.toString + newLine
  
  def makeScalar(scalar: Scalar): String = scalar match {
    case Index(i) => i.toString
    case Real(d) => d.toString
    case Integer(l) => l.toString
    case Text(s) => s.trim
    case Binary(b) => "blob" //TODO: uuencode?
    //TODO: use Scalar.toStringValue?
  //TODO: deal with Time format
  }
    
  def makeTuple(tuple: Tuple): String = tuple match {
    case Sample(d, r) => varToString(d) + " -> " + varToString(r)
    case Tuple(vars) => vars.map(varToString(_)).mkString("(", ",", ")")
  }
  
  def makeFunction(function: Function): String = {
    indent += 5
    val s = function.iterator.map(varToString(_)).mkString(newLine + " "*indent)
    indent -= 5
    s
  }

    
//  def writeVariable(variable: Variable): Unit = variable match {
//    //TODO: build string instead of writing directly? push into super class
//    
//    case Index(i)   => writer.print(i.toString)
//    case Real(d)    => writer.print(d.toString)
//    case Integer(l) => writer.print(l.toString)
//    case Text(s)    => writer.print(s)
//    case Binary(b)  => writer.print(b) //TODO: uuencode?
//    
//    case Tuple(vars) => {
//      //surround Tuple's Variables with parens
//      writer.print("(")
//      //write each Variable contained in this Tuple separated by commas
//      var first = true
//      for (v <- vars) {
//        if (!first) writer.print(",")
//        else first = false
//        writeVariable(v) //recursive
//      }
//      //close parens
//      writer.print(")")
//    }
//    
//    case f: Function => {
//      writer.println()
//      //TODO: "[]" brackets?
//      for (Sample(domain, range) <- f.iterator) {
//        writeVariable(domain)
//        writer.print(" -> ")
//        writeVariable(range)
//        writer.println()
//      }
//    }
//  }

  /**
   * Note, don't close 'out' because it was given to us.
   * TODO: does this violate some principal? 
   *   consider java.io decorator pattern: does closing decorator close decoratee? 
   *   dangerous side effect? 
   *   use case: out from servet response, what happens if we close it here?
   */
  //def close() {}

}

object AsciiWriter {
  
  def apply(out: OutputStream): AsciiWriter = {
    val writer = new AsciiWriter()
    writer._out = out
    writer
  }
  
  def apply(): AsciiWriter = AsciiWriter(System.out)
  
  def write(dataset: Dataset) = AsciiWriter().write(dataset)
}
{'fraction_non_alphanumeric': 0.15048085989062795, 'fraction_numerical': 0.0005657175183858194, 'mean_word_length': 2.4219354838709677, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '3098107', 'n_tokens_mistral': 1716, 'n_tokens_neox': 1679, 'n_words': 455}