<commit_before>//  Copyright © 2016 <NAME>. All rights reserved.

import Prelude

// MARK: - RenderedDocument

indirect enum RenderedDocument: CustomStringConvertible {
	case Fail
	case Empty
	case Char(Character, RenderedDocument)
	case Text(String, RenderedDocument)
	case Line(Int, RenderedDocument)
}

// MARK: RenderedDocument : CustomStringConvertible

extension RenderedDocument {
	var description: String {
		switch self {
		case .Fail, .Empty:
			return ""
		case let .Char(c, doc):
			return String(c) + doc.description
		case let .Text(s, doc):
			return s + doc.description
		case let .Line(i, doc):
			return "\n\(indentation(i))" + doc.description
		}
	}
}

// MARK: - RenderingRule

public enum RenderingRule {
	case Oneline
	case EndIndentation
	
	internal func fits(width: Int, nesting: Int, rest: Int, document: RenderedDocument) -> Bool {
		guard rest >= 0 else {
			return false
		}
		
		switch document {
		case .Fail:
			return false
		case .Empty:
			return true
		case let .Char(_, doc):
			return fits(width, nesting: nesting, rest: rest - 1, document: doc)
		case let .Text(s, doc):
			return fits(width, nesting: nesting, rest: rest - s.characters.count, document: doc)
		case let .Line(i, doc):
			switch self {
			case .Oneline:
				return true
			case .EndIndentation:
				if nesting < i {
					return fits(width, nesting: nesting, rest: width - i, document: doc)
				}else {
					return true
				}
			}
		}
	}
}

// MARK: - Rendering

enum Docs {
	case Nil
	indirect case Cons(Int, Document, Docs)
}

extension Document {
	public func prettify(rule: RenderingRule = .Oneline, width: Int) -> String {
		return self.prettyDocument(rule, width: width).description
	}
	
	internal func prettyDocument(rule: RenderingRule = .Oneline, width: Int) -> RenderedDocument {
		let nicest: (Int, Int, RenderedDocument, RenderedDocument) -> RenderedDocument = { indentation, column, doc1, doc2 in
			if rule.fits(width, nesting: min(indentation, column), rest: width - column, document: doc1) {
				return doc1
			}else {
				return doc2
			}
		}
		let best: (Int, Int, Docs) -> RenderedDocument = fix{ best in
			{ indentation, column, docs in
				switch docs {
				case .Nil:
					return .Empty
				case let .Cons(i, d, ds):
					switch d {
					case .Fail:
						return .Fail
					case .Empty:
						return best(indentation, column, ds)
					case let .Char(c):
						return .Char(c, best(indentation, column + 1, ds))
					case let .Text(str):
						return .Text(str, best(indentation, column + str.characters.count, ds))
					case .Line:
						return .Line(i, best(i, i, ds))
					case let .FlatAlt(x, _):
						return best(indentation, column, .Cons(i, x, ds))
					case let .Cat(x, y):
						return best(indentation, column, .Cons(i, x, .Cons(i, y, ds)))
					case let .Nest(j, x):
						return best(indentation, column, .Cons(i+j, x, ds))
					case let .Union(x, y):
						return nicest(
							indentation,
							column,
							best(indentation, column, .Cons(i, x, ds)),
							best(indentation, column, .Cons(i, y, ds))
						)
					case let .Column(f):
						return best(indentation, column, .Cons(i, f(column), ds))
					case let .Nesting(f):
						return best(indentation, column, .Cons(i, f(i), ds))
					}
				}
			}
		}
		
		return best(0, 0, .Cons(0, self, .Nil))
	}
}

public func prettyString(rule: RenderingRule = .Oneline, width: Int, doc: () -> Document) -> String {
	return doc().prettify(rule, width: width)
}

public func prettyString(rule: RenderingRule = .Oneline, width: Int, doc: Document) -> String {
	return doc.prettify(rule, width: width)
}<commit_msg>Remove one of the prettyString<commit_after>//  Copyright © 2016 <NAME>. All rights reserved.

import Prelude

// MARK: - RenderedDocument

indirect enum RenderedDocument: CustomStringConvertible {
	case Fail
	case Empty
	case Char(Character, RenderedDocument)
	case Text(String, RenderedDocument)
	case Line(Int, RenderedDocument)
}

// MARK: RenderedDocument : CustomStringConvertible

extension RenderedDocument {
	var description: String {
		switch self {
		case .Fail, .Empty:
			return ""
		case let .Char(c, doc):
			return String(c) + doc.description
		case let .Text(s, doc):
			return s + doc.description
		case let .Line(i, doc):
			return "\n\(indentation(i))" + doc.description
		}
	}
}

// MARK: - RenderingRule

public enum RenderingRule {
	case Oneline
	case EndIndentation
	
	internal func fits(width: Int, nesting: Int, rest: Int, document: RenderedDocument) -> Bool {
		guard rest >= 0 else {
			return false
		}
		
		switch document {
		case .Fail:
			return false
		case .Empty:
			return true
		case let .Char(_, doc):
			return fits(width, nesting: nesting, rest: rest - 1, document: doc)
		case let .Text(s, doc):
			return fits(width, nesting: nesting, rest: rest - s.characters.count, document: doc)
		case let .Line(i, doc):
			switch self {
			case .Oneline:
				return true
			case .EndIndentation:
				if nesting < i {
					return fits(width, nesting: nesting, rest: width - i, document: doc)
				}else {
					return true
				}
			}
		}
	}
}

// MARK: - Rendering

enum Docs {
	case Nil
	indirect case Cons(Int, Document, Docs)
}

extension Document {
	public func prettify(rule: RenderingRule = .Oneline, width: Int) -> String {
		return self.prettyDocument(rule, width: width).description
	}
	
	internal func prettyDocument(rule: RenderingRule = .Oneline, width: Int) -> RenderedDocument {
		let nicest: (Int, Int, RenderedDocument, RenderedDocument) -> RenderedDocument = { indentation, column, doc1, doc2 in
			if rule.fits(width, nesting: min(indentation, column), rest: width - column, document: doc1) {
				return doc1
			}else {
				return doc2
			}
		}
		let best: (Int, Int, Docs) -> RenderedDocument = fix{ best in
			{ indentation, column, docs in
				switch docs {
				case .Nil:
					return .Empty
				case let .Cons(i, d, ds):
					switch d {
					case .Fail:
						return .Fail
					case .Empty:
						return best(indentation, column, ds)
					case let .Char(c):
						return .Char(c, best(indentation, column + 1, ds))
					case let .Text(str):
						return .Text(str, best(indentation, column + str.characters.count, ds))
					case .Line:
						return .Line(i, best(i, i, ds))
					case let .FlatAlt(x, _):
						return best(indentation, column, .Cons(i, x, ds))
					case let .Cat(x, y):
						return best(indentation, column, .Cons(i, x, .Cons(i, y, ds)))
					case let .Nest(j, x):
						return best(indentation, column, .Cons(i+j, x, ds))
					case let .Union(x, y):
						return nicest(
							indentation,
							column,
							best(indentation, column, .Cons(i, x, ds)),
							best(indentation, column, .Cons(i, y, ds))
						)
					case let .Column(f):
						return best(indentation, column, .Cons(i, f(column), ds))
					case let .Nesting(f):
						return best(indentation, column, .Cons(i, f(i), ds))
					}
				}
			}
		}
		
		return best(0, 0, .Cons(0, self, .Nil))
	}
}

public func prettyString(rule: RenderingRule = .Oneline, width: Int, doc: () -> Document) -> String {
	return doc().prettify(rule, width: width)
}
{'fraction_non_alphanumeric': 0.1276655839570682, 'fraction_numerical': 0.0042366897330885465, 'mean_word_length': 2.9786516853932583, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 22, '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': '5364470', 'n_tokens_mistral': 2936, 'n_tokens_neox': 2347, 'n_words': 740}