Skip to content

Instantly share code, notes, and snippets.

@jasonqu
Last active August 19, 2016 10:46
Show Gist options
  • Save jasonqu/56a6a17a74235e2ac70030e0323b27d7 to your computer and use it in GitHub Desktop.
Save jasonqu/56a6a17a74235e2ac70030e0323b27d7 to your computer and use it in GitHub Desktop.
格式化markdown表格
#!/bin/sh
exec scala "$0" "$@"
!#
/**
* 目标:格式化md table 表格语法 http://www.tablesgenerator.com/markdown_tables
* 注意点:文件的编码 涉及到字符串长度的计算
*/
if (args.length < 1 || args.length > 2) {
println(
"""Usage: scala NormaMdTable.scala inputMdFile [outputMdFile]
| * inputMdFile: the path of the inputFile, eg. a.md
| * inputMdFile: the path of the outputFile, if not specified will add a ".md" postfix
""".stripMargin)
} else {
process(args(0), if (args.length == 2) args(1) else args(0) + ".md")
}
def process(in: String, out: String) = {
val source = recurProcess(
scala.io.Source.fromFile(args(0), "utf-8").getLines(), List[String]()).reverse
import java.io._
val pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(out), "UTF-8"))
pw.write(source.mkString("\n"))
pw.close()
println(s"generate new file in $out")
}
def recurProcess(source: Iterator[String], content: List[String]): List[String] = {
if (!source.hasNext) content
else {
val line = source.next()
if (line.startsWith("|")) {
val (tableRest, rest) = source.span(_.startsWith("|"))
recurProcess(rest, beautifyMdTable(line +: tableRest.toSeq) :: content)
} else {
recurProcess(source, line :: content)
}
}
}
def beautifyMdTable(table: Seq[String]): String = {
def extractContent(table: Seq[String]): Seq[Array[String]] =
(table.head +: table.drop(2)).foldRight(Seq[Array[String]]()) { (line, contents) =>
line.substring(1).split("\\|").map(_.trim) +: contents
}
def calcDisplayLength(x : String) = {
// http://stackoverflow.com/questions/28761385/single-chinese-character-determined-as-length-2-in-java-scala-string useless?
// http://zhidao.baidu.com/question/271624295.html
//x.length + x.count(c => Character.isIdeographic(c) || (c >= 12288 && c <= 12330) || c > 65248)
x.length * 2 - x.count(_.toInt < 1000)
}
val contents = extractContent(table)
// 要考虑中文字符
val beforetrans = contents.map(_.length)
if(!beforetrans.forall(_ == beforetrans.head))
println(s"processing $beforetrans with ${contents.map(_.toList)}")
val maxlengths: Array[Int] = contents.map(_.map(calcDisplayLength)).transpose.map(_.max + 2).toArray
def getTableMd(line: Array[String]): String = {
val beautified = for (i <- line.indices)
yield " " + line(i) + " " * (maxlengths(i) - calcDisplayLength(line(i)) - 1)
beautified.mkString("|", "|", "|")
}
def second = maxlengths.map("-" * _).mkString("|", "|", "|")
(getTableMd(contents.head) +: second +: contents.tail.map(getTableMd)).mkString("\n")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment