diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..998c106 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# binary +um diff --git a/next/next.go b/next/next.go index 29ccc86..8877484 100644 --- a/next/next.go +++ b/next/next.go @@ -5,10 +5,10 @@ import ( "fmt" "log" "os" - "os/exec" "regexp" "strconv" "strings" + "time" "github.com/brtholomy/um/go/cmd" "github.com/brtholomy/um/go/flags" @@ -23,6 +23,9 @@ const ( const FILE_REGEXP = `(?m)^([0-9]+)\.[^\.]*\.*md$` +// TODO: consider supporting a config file, since my preference for dots here is not precisely ISO8601. +const DATE_FORMAT = "2006.01.02" + var fileRegexp *regexp.Regexp = regexp.MustCompile(FILE_REGEXP) type options struct { @@ -34,7 +37,7 @@ type options struct { func initOpts() options { return options{ flags.Arg{"", "midfix file descriptor"}, - flags.Arg{"", "tags to add to new file"}, + flags.Arg{"", "tags to add to new file, comma separated. '+' will add file descriptor as tag"}, flags.Bool{"--help", "-h", false, "show help"}, } } @@ -72,39 +75,33 @@ func next(last string, desc string) (string, error) { return n, nil } -// calls (um--header) inside a running emacs server. which has the advantage of fetching the loaded -// value of um-date-format, and respecting any other loaded configuration we might add. +// writes the header string to the filename. // -// other options would be to forego respecting Elisp config values, or loading from a common config -// file and forcing emacs to load from there - which would be very un-Emacs. -// -// this is the point at which this design becomes weird. But I don't want to let Elisp suck this CLI -// into its nasty grip. Go is far superior in this application and there's no way I'm writing the -// `um tag` logic in Elisp. +// NOTE: we used to call into emacsclient to get config values, but I want separation of concern +// betweeen the CLI and the emacs um-mode. // // So I've got Go and and an ancient beloved Lisp machine trying to live together. -func emacsHeader(f string, tags string) error { - quotedargs := fmt.Sprintf(`"%s"`, f) +func writeHeader(f, tags, descriptor string) error { + headerFmt := `# %s +: %s +%s` + tagsStr := "" + // WARN: strings.Split will return the whole string when no match, even when the input string is + // empty. Thus this ugly dance to ensure an empty slice. + var tagsX []string if tags != "" { - quotedargs = fmt.Sprintf(`%s "%s"`, quotedargs, tags) + tagsX = strings.Split(tags, ",") } - fn := fmt.Sprintf(`(um--header %s)`, quotedargs) - // NOTE: no longer get any string back from the lisp function: - out, err := exec.Command("emacsclient", "--eval", fn).Output() - if err != nil { - return fmt.Errorf("emacsclient: %w", err) + for _, t := range tagsX { + if t == "+" { + t = descriptor + } + tagsStr += fmt.Sprintf("+ %s\n", t) } - // NOTE: grabbing from stdout adds a newline: - header := strings.TrimRight(string(out), "\n") - // NOTE: Unquote will convert \\n to \n and remove \": - header, err = strconv.Unquote(header) - if err != nil { - return fmt.Errorf("strconv.Unquote: %w", err) - } - if err := os.WriteFile(f, []byte(header), 0644); err != nil { - return err - } - return nil + // NOTE: always needs the trailing newline. + tagsStr += "\n" + header := fmt.Sprintf(headerFmt, f, time.Now().Format(DATE_FORMAT), tagsStr) + return os.WriteFile(f, []byte(header), 0644) } func Next(args []string) { @@ -125,7 +122,7 @@ func Next(args []string) { if err != nil { log.Fatalf("um %s: %v", CMD, err) } - if err := emacsHeader(filename, opts.Tags.Val); err != nil { + if err := writeHeader(filename, opts.Tags.Val, opts.Descriptor.Val); err != nil { log.Fatalf("um %s: %v", CMD, err) } // NOTE: sends filename to stdout for piping