regexghost-dotfiles

My dotfiles and scripts
git clone git@git.regexghost.com/regexghost-dotfiles.git
Log | Files | Refs | README

tablealigner.go (4210B)


      1 package main
      2 
      3 import (
      4 	"fmt"
      5 	"unicode/utf8"
      6 	"os"
      7 	"strings"
      8 	"regexp"
      9 	"os/exec"
     10 	//"strconv"
     11 )
     12 
     13 func Print(str string) {
     14 	cmd := exec.Command("notify-send", str)
     15 	cmd.Run()
     16 }
     17 
     18 var EMOJIS []rune = []rune{'❌', '✅', '❔', '❓', '📅', '🚗', '🌙', '⏳'}
     19 
     20 func isEmoji(r rune) bool {
     21 	for _, emoji := range EMOJIS {
     22 		if r == emoji {
     23 			return true
     24 		}
     25 	}
     26 	return false
     27 }
     28 
     29 func properLen(input string) int {
     30 	var noEndSpaces string = strings.TrimRight(input, " ")
     31 	var length int = utf8.RuneCountInString(noEndSpaces) + 1
     32 	
     33 	//fmt.Printf("A:%s:B\n", input)
     34 	//fmt.Printf("C:%s:D\n", noEndSpaces)
     35 	
     36 	for _, r := range noEndSpaces {
     37 		if isEmoji(r) {
     38 			length++
     39 		}
     40 	}
     41 	return length
     42 }
     43 
     44 func readFile(filename string) []string {
     45 	dat, err := os.ReadFile(filename)
     46 	if err != nil {
     47 		panic(err)
     48 	}
     49 	
     50 	return strings.Split(string(dat), "\n")
     51 }
     52 
     53 func testForAlignRow(line string) bool {
     54 	if len(line) < 1 {
     55 		return false
     56 	}
     57 	
     58 	if line[0] != '|' || line[len(line)-1] != '|' {
     59 		return false
     60 	}
     61 	split := strings.Split(line, "|")
     62 	var isCorrect = regexp.MustCompile("^(-*:* *)*$").MatchString
     63 	for _, x := range split {
     64 		if !isCorrect(x) {
     65 			return false
     66 		}
     67 	}
     68 	
     69 	return true
     70 }
     71 
     72 func testForEnd(line string) bool {
     73 	if len(line) == 0 || line[0] != '|' {
     74 		return true
     75 	}
     76 	return false
     77 }
     78 
     79 func findTables(input []string) [][]int {
     80 	var tables [][]int
     81 	
     82 	var inTable bool = false
     83 	
     84 	for i, line := range input {
     85 		if !inTable && testForAlignRow(line) {
     86 			tables = append(tables, []int{i-1})
     87 			inTable = true
     88 		} else if inTable && testForEnd(line) {
     89 			tables[len(tables)-1] = append(tables[len(tables)-1], i-1)
     90 			inTable = false
     91 		}
     92 	}
     93 	
     94 	return tables
     95 }
     96 
     97 func calcLengths(thisTable []string) []int {
     98 	numCells := strings.Count(thisTable[0], "|") - 1
     99 
    100 	if numCells < 1 {
    101 		os.Exit(1)
    102 	}
    103 	
    104 	var columnLengths []int = make([]int, numCells)
    105 	
    106 	for i, line := range thisTable {
    107 		if i == 1 {
    108 			continue
    109 		}
    110 		cells := strings.Split(line, "|")
    111 		cells = cells[1:len(cells)-1]
    112 		
    113 		for j, cell := range cells {
    114 			var cellLen int = properLen(cell)
    115 			//fmt.Println(cell)
    116 			if cellLen > columnLengths[j] {
    117 				columnLengths[j] = cellLen
    118 			}
    119 		}
    120 	}
    121 	return columnLengths
    122 }
    123 
    124 func alignTable(table []int, data[]string) []string {
    125 	//fmt.Println("Table:")
    126 	thisTable := data[table[0]:table[1]+1]
    127 	columnLengths := calcLengths(thisTable)
    128 	//fmt.Println(columnLengths)
    129 	
    130 	for i:=0; i<len(thisTable); i++ {
    131 		cells := strings.Split(thisTable[i], "|")
    132 		cells = cells[1:len(cells)-1]
    133 		
    134 		newCells := []string{}
    135 		for j, cell := range cells {
    136 			cell = strings.TrimRight(cell, " ") + " "
    137 			var cellLen int = properLen(cell)
    138 			if cellLen != columnLengths[j] {
    139 				var paddedCell string = padCell(cell, cellLen, i, j, columnLengths)
    140 				newCells = append(newCells, paddedCell)
    141 				
    142 			} else {
    143 				newCells = append(newCells, cell)
    144 			}
    145 		}
    146 		// Build new row string
    147 		var newCellString string = "|"
    148 		for _, cell := range newCells {
    149 			newCellString = newCellString + cell + "|"
    150 		}
    151 		thisTable[i] = newCellString
    152 	}
    153 	return data
    154 }
    155 
    156 func padCell(cell string, cellLen int, i int, j int, columnLengths []int) string {
    157 	var paddedCell string
    158 	if i == 1 {
    159 		paddedCell = " :" + strings.Repeat("-", columnLengths[j]-4) + ": "
    160 	} else {
    161 		paddedCell = cell + strings.Repeat(" ", columnLengths[j]-cellLen)
    162 	}
    163 	return paddedCell
    164 }
    165 
    166 func alignTables(tables [][]int, data []string) []string {
    167 	for _, table := range tables {
    168 		data = alignTable(table, data)
    169 	}
    170 	return data
    171 }
    172 
    173 func saveToFile(data []string, filename string) {
    174 	if len(data[len(data)-1]) == 0 {
    175 		data = data[:len(data)-1]
    176 	}
    177 	var toSave string
    178 	for _, line := range data {
    179 		toSave = toSave + line + "\n"
    180 	}
    181 	err := os.WriteFile(filename, []byte(toSave), 0666)
    182 	if err != nil {
    183 		panic(err)
    184 	}
    185 }
    186 
    187 func main() {
    188 	if len(os.Args) != 3 {
    189 		fmt.Println("Usage: \n  tablealigner input.md output.md")
    190 		panic("wrong args")
    191 	}
    192 	
    193 	var inputFile string = os.Args[1]
    194 	var outputFile string = os.Args[2]
    195 	if os.Args[1] == "-s" {
    196 		inputFile = os.Args[2]
    197 		outputFile = os.Args[2]
    198 	}
    199 		
    200 	data := readFile(inputFile)
    201 	
    202 	tables := findTables(data)
    203 	//fmt.Println(tables)
    204 	data = alignTables(tables, data)
    205 	
    206 	//data = fixEmojis(data)
    207 	
    208 	saveToFile(data, outputFile)
    209 }