~dvshkn/planfile

ref: 34ce4118513c1048ed016eed0bde9d14435c1ad5 planfile/utils/files.go -rw-r--r-- 2.5 KiB
34ce4118David Knight first post 10 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package utils

import(
	"bufio"
	"os"
	"strings"
)

func transformer(line string) (bool, string) {
	if len(strings.TrimSpace(line)) == 0 {
		// keep whitespace
		return true, ""
	} else if strings.HasPrefix(line, "_ ") {
		// keep open tasks
		return true, line
	} else if strings.HasPrefix(line, "* ") {
		// remove completed tasks
		return false, ""
	} else if strings.HasPrefix(line, "x ") {
		// remove abandoned tasks
		return false, ""
	} else if strings.HasPrefix(line, "t ") {
		// keep tomorrow tasks, convert to open tasks
		return true, "_ " + strings.TrimPrefix(line, "t ")
	} else if strings.HasPrefix(line, "> ") {
		// keep notes
		return true, line
	}
	return false, ""
}

func CreateEmpty(name string) error {
	f, err := os.Create(name)
	f.Close()
	return err
}

func CreateFrom(destName string, srcName string) error {
	srcFile, err := os.Open(srcName)
	if err != nil {
		return err
	}
	defer srcFile.Close()

	destFile, err := os.Create(destName)
	if err != nil {
		return err
	}
	defer destFile.Close()

	var newTasks strings.Builder
	var builder strings.Builder
	var destContent string

	// process source planfile
	lastTaskIdx := -1
	scanner := bufio.NewScanner(srcFile)
	for scanner.Scan() {
		srcLine := scanner.Text()
		keep, destLine := transformer(srcLine)

		// TODO: refactor this so more of the line type logic is contained
		//		 in the transformer function
		if keep {
			if strings.HasPrefix(srcLine, "t ") {
				// store "tomorrow" tasks separately so we can choose where
				// to insert them after reading the source planfile
				newTasks.WriteString(destLine)
				newTasks.WriteByte('\n')
			} else {
				builder.WriteString(destLine)
				builder.WriteByte('\n')

				if strings.HasPrefix(srcLine, "_ ") {
					lastTaskIdx = builder.Len()
				}
			}
		}
	}
	if scanner.Err() != nil {
		return scanner.Err()
	}

	// produce destination planfile
	if newTasks.Len() > 0 {
		// decide where to put converted "tomorrow" tasks
		if lastTaskIdx == -1 {
			// no open tasks, insert at beginning of file
			destContent = newTasks.String() + builder.String()
		} else if lastTaskIdx == builder.Len() {
			// file ends with an open task, append to end
			destContent = builder.String() + newTasks.String()
		} else {
			// last open task in middle of file, do an insertion
			temp := builder.String()
			destContent = temp[:lastTaskIdx] + newTasks.String() + temp[lastTaskIdx:]
		}
	} else {
		destContent = builder.String()
	}
	destContent = strings.TrimSpace(destContent) + "\n"
	destFile.WriteString(destContent)

	return nil
}