mirror of
https://github.com/RWejlgaard/org.git
synced 2026-05-06 04:34:45 +00:00
132 lines
3 KiB
Go
132 lines
3 KiB
Go
package parser
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/rwejlgaard/org/internal/model"
|
|
)
|
|
|
|
// Save writes the org file back to disk
|
|
func Save(orgFile *model.OrgFile) error {
|
|
file, err := os.Create(orgFile.Path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer file.Close()
|
|
|
|
writer := bufio.NewWriter(file)
|
|
defer writer.Flush()
|
|
|
|
for _, item := range orgFile.Items {
|
|
if err := writeItem(writer, item); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// writeItem recursively writes an item and its children
|
|
func writeItem(writer *bufio.Writer, item *model.Item) error {
|
|
// Write heading
|
|
stars := strings.Repeat("*", item.Level)
|
|
line := stars
|
|
if item.State != model.StateNone {
|
|
line += " " + string(item.State)
|
|
}
|
|
if item.Priority != model.PriorityNone {
|
|
line += " [#" + string(item.Priority) + "]"
|
|
}
|
|
line += " " + item.Title + "\n"
|
|
|
|
if _, err := writer.WriteString(line); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Write scheduling info if not already in notes
|
|
hasScheduled := false
|
|
hasDeadline := false
|
|
hasLogbook := false
|
|
hasProperties := false
|
|
for _, note := range item.Notes {
|
|
if strings.Contains(note, "SCHEDULED:") {
|
|
hasScheduled = true
|
|
}
|
|
if strings.Contains(note, "DEADLINE:") {
|
|
hasDeadline = true
|
|
}
|
|
if strings.Contains(note, ":LOGBOOK:") {
|
|
hasLogbook = true
|
|
}
|
|
if strings.Contains(note, ":PROPERTIES:") {
|
|
hasProperties = true
|
|
}
|
|
}
|
|
|
|
if item.Scheduled != nil && !hasScheduled {
|
|
scheduledLine := fmt.Sprintf("SCHEDULED: <%s>\n", FormatOrgDate(*item.Scheduled))
|
|
if _, err := writer.WriteString(scheduledLine); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
if item.Deadline != nil && !hasDeadline {
|
|
deadlineLine := fmt.Sprintf("DEADLINE: <%s>\n", FormatOrgDate(*item.Deadline))
|
|
if _, err := writer.WriteString(deadlineLine); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// Write effort in :PROPERTIES: drawer if not already in notes
|
|
if item.Effort != "" && !hasProperties {
|
|
if _, err := writer.WriteString(":PROPERTIES:\n"); err != nil {
|
|
return err
|
|
}
|
|
effortLine := fmt.Sprintf(":EFFORT: %s\n", item.Effort)
|
|
if _, err := writer.WriteString(effortLine); err != nil {
|
|
return err
|
|
}
|
|
if _, err := writer.WriteString(":END:\n"); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// Write clock entries in :LOGBOOK: drawer if not already in notes
|
|
if len(item.ClockEntries) > 0 && !hasLogbook {
|
|
if _, err := writer.WriteString(":LOGBOOK:\n"); err != nil {
|
|
return err
|
|
}
|
|
for _, entry := range item.ClockEntries {
|
|
clockLine := fmt.Sprintf("CLOCK: [%s]", formatClockTimestamp(entry.Start))
|
|
if entry.End != nil {
|
|
clockLine += fmt.Sprintf("--[%s]", formatClockTimestamp(*entry.End))
|
|
}
|
|
clockLine += "\n"
|
|
if _, err := writer.WriteString(clockLine); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if _, err := writer.WriteString(":END:\n"); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// Write notes
|
|
for _, note := range item.Notes {
|
|
if _, err := writer.WriteString(note + "\n"); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// Write children
|
|
for _, child := range item.Children {
|
|
if err := writeItem(writer, child); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|