src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

note.go (2464B)


      1 package command
      2 
      3 import (
      4 	"errors"
      5 	"fmt"
      6 	"io"
      7 	"os"
      8 	"os/exec"
      9 	"strings"
     10 	"time"
     11 
     12 	"code.dwrz.net/src/pkg/dqs/command/help"
     13 	"code.dwrz.net/src/pkg/dqs/entry"
     14 	"code.dwrz.net/src/pkg/dqs/store"
     15 )
     16 
     17 var Note = &command{
     18 	execute: setNote,
     19 
     20 	description: "set a note on an entry",
     21 	help:        help.Note,
     22 	name:        "note",
     23 }
     24 
     25 func setNote(args []string, date time.Time, store *store.Store) error {
     26 	u, err := store.GetUser()
     27 	if err != nil && !errors.Is(err, os.ErrNotExist) {
     28 		return fmt.Errorf("failed to get user: %w", err)
     29 	}
     30 	if u == nil {
     31 		return Config.execute(args, date, store)
     32 	}
     33 
     34 	e, err := store.GetEntry(date.Format(entry.DateFormat))
     35 	if err != nil && !errors.Is(err, os.ErrNotExist) {
     36 		return fmt.Errorf("failed to get entry: %w", err)
     37 	}
     38 	if e == nil {
     39 		e = entry.New(date, u)
     40 	}
     41 
     42 	if len(args) == 0 {
     43 		fmt.Println(e.Note)
     44 
     45 		return nil
     46 	}
     47 
     48 	update, args := args[0], args[1:]
     49 	switch update {
     50 	case "append":
     51 		if len(args) >= 1 {
     52 			if len(e.Note) == 0 {
     53 				e.Note = strings.Join(args, " ")
     54 			} else {
     55 				e.Note = fmt.Sprintf(
     56 					"%s\n%s", e.Note,
     57 					strings.Join(args, " "),
     58 				)
     59 			}
     60 		}
     61 
     62 	case "delete":
     63 		e.Note = ""
     64 
     65 	case "edit":
     66 		var err error
     67 		e.Note, err = editNote(e.Note)
     68 		if err != nil {
     69 			return err
     70 		}
     71 
     72 	case "set":
     73 		if len(args) >= 1 {
     74 			e.Note = strings.Join(args, " ")
     75 		}
     76 
     77 	default:
     78 		fmt.Println(e.Note)
     79 	}
     80 
     81 	if err := store.UpdateEntry(e); err != nil {
     82 		return fmt.Errorf("failed to store entry: %w", err)
     83 	}
     84 
     85 	return nil
     86 }
     87 
     88 func editNote(note string) (string, error) {
     89 	// If no note is specified, take input from the user's editor.
     90 	// Write the entry to the temporary file.
     91 	temp, err := os.CreateTemp(os.TempDir(), "dqs-*")
     92 	if err != nil {
     93 		return "", err
     94 	}
     95 	defer temp.Close()
     96 
     97 	_, err = temp.Write([]byte(note))
     98 	if err != nil {
     99 		return "", err
    100 	}
    101 
    102 	editor := os.Getenv("EDITOR")
    103 
    104 	args := strings.Split(editor, " ")
    105 	args = append(args, temp.Name())
    106 
    107 	path, err := exec.LookPath(args[0])
    108 	if err != nil {
    109 		return "", fmt.Errorf(
    110 			"failed to find $EDITOR %s: %w", editor, err,
    111 		)
    112 	}
    113 
    114 	cmd := exec.Cmd{
    115 		Path:   path,
    116 		Args:   args,
    117 		Stdin:  os.Stdin,
    118 		Stdout: os.Stdout,
    119 		Stderr: os.Stderr,
    120 	}
    121 	if err := cmd.Run(); err != nil {
    122 		return "", err
    123 	}
    124 
    125 	if _, err := temp.Seek(0, 0); err != nil {
    126 		return "", err
    127 	}
    128 
    129 	data, err := io.ReadAll(temp)
    130 	if err != nil {
    131 		return "", err
    132 	}
    133 
    134 	if err := os.Remove(temp.Name()); err != nil {
    135 		return "", err
    136 	}
    137 
    138 	return string(data), nil
    139 }