adding nested header support (mostly in summary); gofmt

This commit is contained in:
Dan Ballard 2018-05-21 13:52:50 -07:00
parent f20fd9f966
commit edb3d69cfd
5 changed files with 107 additions and 46 deletions

View File

@ -1,13 +1,13 @@
package main
import (
"os"
"time"
"log"
"github.com/dballard/markdown-bullet-journal/process"
"fmt"
"github.com/dballard/markdown-bullet-journal/process"
"log"
"os"
"strconv"
"strings"
"time"
)
const template = `# Work
@ -40,11 +40,11 @@ func (ph *processHandler) Writeln(line string) {
func (ph *processHandler) Eof() {}
func (ph *processHandler) NewFile() {}
func (ph *processHandler) ProcessLine(line string, indentLevel int, stack []string, todo bool, done bool, repTask process.RepTask) {
func (ph *processHandler) ProcessLine(line string, indentLevel int, headerStack []string, lineStack []string, todo bool, done bool, repTask process.RepTask) {
// TODO: handle [x] numXnum
if !done || repTask.Is {
if repTask.Is {
ph.Writeln(strings.Repeat("\t", indentLevel) + "- [ ] 0x" + strconv.Itoa(repTask.B) + stack[len(stack)-1] )
ph.Writeln(strings.Repeat("\t", indentLevel) + "- [ ] 0x" + strconv.Itoa(repTask.B) + lineStack[len(lineStack)-1])
} else {
ph.Writeln(line)
}

View File

@ -22,6 +22,20 @@
- [ ] not done
- note
# Nested Header
## With Nothing
- note
- [ ] undone
## With something done
- more notes
- [ ] a partly done thing
- [ ] more to do
- [x] the one done thing
# Repetition
- [x] 5x5 things

View File

@ -1,19 +1,23 @@
package main
import (
"runtime"
"os"
"github.com/dballard/markdown-bullet-journal/process"
"log"
"os"
"runtime"
"strconv"
"strings"
)
type header struct {
text string
printed bool
}
type processHandler struct {
File *os.File
totalCount, doneCount int
header string
headerPrinted bool
headers []header
}
func (ph *processHandler) Writeln(line string) {
@ -23,23 +27,36 @@ func (ph *processHandler) Writeln(line string) {
func (ph *processHandler) NewFile() {
ph.totalCount = 0
ph.doneCount = 0
ph.header = ""
ph.headerPrinted = false
ph.headers = []header{}
}
func (ph *processHandler) Eof() {
ph.Writeln(strconv.Itoa(ph.doneCount) + " / " + strconv.Itoa(ph.totalCount))
}
func (ph *processHandler) ProcessLine(line string, indentLevel int, stack []string, todo bool, done bool, repTask process.RepTask) {
func (ph *processHandler) handleHeaderPrint() {
for i, header := range ph.headers {
if ! header.printed {
ph.Writeln("\t" + strings.Repeat("#", i+1) + " " + header.text)
ph.headers[i].printed = true
}
}
}
func (ph *processHandler) ProcessLine(line string, indentLevel int, headerStack []string, lineStack []string, todo bool, done bool, repTask process.RepTask) {
if strings.Trim(line, " \t\n\r") == "" {
return
}
if line[0] == '#' {
ph.header = line[2:]
ph.headerPrinted = false;
return
last := headerStack[len(headerStack)-1]
if len(headerStack) > len(ph.headers) {
ph.headers = append(ph.headers, header{ last, false })
} else if len(headerStack) == len(ph.headers) {
ph.headers[len(ph.headers)-1] = header{last, false}
} else if len(headerStack) < len(ph.headers) {
ph.headers = ph.headers[: len(headerStack)]
ph.headers[len(ph.headers)-1] = header{last, false}
}
}
// inc count of todo items (rep tasks shouldnt count towards outstanding todo, unless done)
@ -48,10 +65,7 @@ func (ph *processHandler) ProcessLine(line string, indentLevel int, stack []stri
}
if done {
if !ph.headerPrinted {
ph.Writeln("\t# " + ph.header)
ph.headerPrinted = true
}
ph.handleHeaderPrint()
ph.doneCount += 1
repStr := ""
if repTask.Is {
@ -59,7 +73,7 @@ func (ph *processHandler) ProcessLine(line string, indentLevel int, stack []stri
// inc todo count here since we did a thing, its done, and we dont want a higher done count than total
ph.totalCount += 1
}
ph.Writeln("\t\t" + repStr + strings.Join(stack, " / "))
ph.Writeln("\t\t" + repStr + strings.Join(lineStack, " / "))
}
}

View File

@ -16,9 +16,12 @@ const EXPECTED = `
# Test Data
nesting1 / nesting 2 / nesting 3 / nesting 4 / nesting 5
not nested
# Nested Header
## With something done
a partly done thing / the one done thing
# Repetition
25 things
4 / 11
5 / 15
`
func TestSummary(t *testing.T) {
@ -54,6 +57,6 @@ func TestSummary(t *testing.T) {
line := strings.Count(string(result[:diffLoc]), "\n")
errorStr := string(result[int(math.Max(0, float64(diffLoc - 10))) : int(math.Min(float64(len(result)), float64(diffLoc + 10))) ])
t.Errorf("Summary results do not match expected:\nfirst difference at line %v: '%v'\n%v<---->\n%v\n", line, errorStr, string(result), EXPECTED)
t.Errorf("Summary results do not match expected:\nfirst difference at line %v\nexpected char: '%c'\nactual char: '%v'\nline: '%v'\n%v<---->\n%v\n", line, EXPECTED[diffLoc], string(result[diffLoc]), errorStr, string(result), EXPECTED)
}
}

View File

@ -1,23 +1,31 @@
package process
import (
"os"
"log"
"bufio"
"regexp"
"io/ioutil"
"log"
"os"
"regexp"
"strconv"
"strings"
)
var (
repTaskRegExp = regexp.MustCompile("^([0-9]*)[xX]([0-9]*)")
headerExp = regexp.MustCompile("^(#+) *(.+)")
)
type RepTask struct {
Is bool
A, B int
}
type Flags struct {
}
type ProcessHandler interface {
Writeln(line string)
ProcessLine(line string, indentLevel int, stack []string, todo bool, done bool, repTask RepTask)
ProcessLine(line string, indentLevel int, headerStack []string, lineStack []string, todo bool, done bool, repTask RepTask)
Eof()
NewFile()
}
@ -40,6 +48,14 @@ func GetFiles() (filteredFiles []string) {
return
}
func max(x, y int) int {
if x >= y {
return x
} else {
return y
}
}
func ProcessFile(ph ProcessHandler, fileName string) {
file, err := os.Open(fileName)
if err != nil {
@ -48,7 +64,9 @@ func ProcessFile(ph ProcessHandler, fileName string) {
defer file.Close()
ph.NewFile()
stack := make([]string, 0)
headerStack := make([]string, 1)
lineStack := make([]string, 0)
//flags := Flags{}
scanner := bufio.NewScanner(file)
indentPattern := ""
@ -71,22 +89,35 @@ func ProcessFile(ph ProcessHandler, fileName string) {
} else {
indentLevel = strings.Count(startSpaces.FindString(line), indentPattern)
}
if headerExp.MatchString(line) {
matches := headerExp.FindStringSubmatch(line)
if len(matches[1]) > len(headerStack) {
headerStack = append(headerStack, matches[2])
} else if len(matches[1]) == len(headerStack) {
headerStack[len(headerStack)-1] = matches[2]
} else if len(matches[1]) < len(headerStack) {
headerStack = headerStack[:len(matches[1])]
headerStack[len(headerStack)-1] = matches[2]
}
}
todo := false
done := false
var repTask RepTask
if indentLevel < len(stack)-1 {
stack = stack[: indentLevel+1]
if indentLevel < len(lineStack)-1 {
lineStack = lineStack[:indentLevel+1]
}
if indentLevel == len(stack)-1 {
stack[len(stack)-1], todo, done, repTask = getText(line, indentLevel, indentPattern)
if indentLevel == len(lineStack)-1 {
lineStack[len(lineStack)-1], todo, done, repTask = getText(line, indentLevel, indentPattern)
}
if indentLevel >= len(stack) {
if indentLevel >= len(lineStack) {
row := ""
row, todo, done, repTask = getText(line, indentLevel, indentPattern)
stack = append(stack, row)
lineStack = append(lineStack, row)
}
ph.ProcessLine(line, indentLevel, stack, todo, done, repTask)
ph.ProcessLine(line, indentLevel, headerStack, lineStack, todo, done, repTask)
}
ph.Eof()
}
@ -110,7 +141,6 @@ func getText(str string, indentLevel int, indentPattern string) (text string, to
text = text[4:]
}
repTaskRegExp := regexp.MustCompile("^([0-9]*)[xX]([0-9]*)")
if repTaskRegExp.MatchString(text) {
repTask.Is = true
matches := repTaskRegExp.FindStringSubmatch(text)