Skip to content

Instantly share code, notes, and snippets.

@kbilsted
Created April 14, 2016 06:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kbilsted/d8d38a3b76da8096aa4fb9e7b3363427 to your computer and use it in GitHub Desktop.
Save kbilsted/d8d38a3b76da8096aa4fb9e7b3363427 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
namespace MarkDownTableReformatter
{
class Program
{
static void Main(string[] args)
{
var path = args[0];
var result = FormatBlock(File.ReadLines(path).ToArray());
var text = MakeString(result);
File.WriteAllText(path + "2", text, Encoding.UTF8);
}
private static string MakeString(List<List<string>> lines)
{
StringBuilder sb = new StringBuilder();
foreach (var line in lines)
{
foreach (var cell in line)
sb.Append(cell);
sb.AppendLine();
}
return sb.ToString();
}
private static List<List<string>> FormatBlock(string[] textLines)
{
var cellLines = textLines
.Select((x,i) => new {line=x.Trim(), lineno=i})
.Where(x=>!string.IsNullOrWhiteSpace(x.line))
.Select(x => SplitLine(x.line, x.lineno))
.ToList();
var maxColumnCount = cellLines.Select(line => line.Count).Max();
NormalizeAllLinesToSameColumnCount(cellLines, maxColumnCount);
PadColumnsToSameWidth(maxColumnCount, cellLines);
return cellLines;
}
private static void PadColumnsToSameWidth(int maxColumnCount, List<List<string>> cellLines)
{
for (int col = 0; col < maxColumnCount; col++)
{
var maxColumnWidth = cellLines.Select(x => x[col].Length).Max();
foreach (var cellLine in cellLines)
cellLine[col] = PadColumnToWidth(cellLine, col, maxColumnWidth);
}
}
private static string PadColumnToWidth(List<string> cellLine, int col, int maxColumnWidth)
{
var cell = cellLine[col];
if (cell.Length < maxColumnWidth)
return cell.Substring(0, cell.Length - 1).PadRight(maxColumnWidth-1) + cell.Last();
return cell;
}
private static void NormalizeAllLinesToSameColumnCount(List<List<string>> cellLines, int maxColumns)
{
foreach (var cellLine in cellLines)
{
if (cellLine.Count < maxColumns)
{
for (int i = 0; i < maxColumns - cellLine.Count; i++)
cellLine.Add("|");
}
}
}
private static List<string> SplitLine(string line, int lineno)
{
if (!line.StartsWith("^") && !line.StartsWith("|"))
throw new Exception(string.Format("Cannot parse line. Needs to start with characters ^ or | at line {0}. Content: '{1}'", lineno, line));
char separator = line[0];
List<string> elements = new List<string>();
elements.Add(separator.ToString());
int pos = 1;
while (pos < line.Length)
{
var cell = GetCell(line, pos, separator, lineno);
pos += cell.Length;
elements.Add(" "+cell.Trim());
}
return elements;
}
private static string GetCell(string line, int pos, char separator, int lineno)
{
bool isInsideLinkScope = false;
for (int i = pos; i < line.Length; i++)
{
if (isInsideLinkScope)
{
if (line[i] == ']' && line.Length > i + 1 && line[i + 1] == ']')
{
isInsideLinkScope = false;
i++;
}
continue;
}
if (line[i] == '[' && line.Length > i + 1 && line[i + 1] == '[')
{
isInsideLinkScope = true;
i++;
continue;
}
if (line[i] == separator)
return line.Substring(pos, i - pos + 1);
}
if (isInsideLinkScope)
throw new Exception(string.Format("Did not find a closing link scope ']]' at line {0}", lineno));
throw new Exception(string.Format("Did not find a separator '{0}' for cell at line {1}", separator, lineno));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment