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 }