summaryrefslogtreecommitdiff
path: root/main.go
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-08-01 16:18:19 -0300
committerGabriel Schneider <[email protected]>2026-08-01 18:21:40 -0300
commit151ea12251ed876aa87bb486da1bc337e25369e9 (patch)
tree0363d90b5df6fc8b17b1737ef2793ba3825ba4d4 /main.go
parent8ec4e135e318c7799b2576a8729493c063da4a97 (diff)
downloadnotevi-151ea12251ed876aa87bb486da1bc337e25369e9.tar.gz
notevi-151ea12251ed876aa87bb486da1bc337e25369e9.zip
Diffstat (limited to 'main.go')
-rw-r--r--main.go53
1 files changed, 45 insertions, 8 deletions
diff --git a/main.go b/main.go
index e0ac598..6876a8c 100644
--- a/main.go
+++ b/main.go
@@ -45,6 +45,7 @@ type Entry struct {
Pattern string `json:"pattern,omitempty"`
Matches int `json:"matches,omitempty"`
NoteID int `json:"note_id,omitempty"`
+ ReplyTo int `json:"reply_to,omitempty"`
Type string `json:"type,omitempty"`
Text string `json:"text,omitempty"`
}
@@ -94,9 +95,10 @@ usage:
vr grep [-log FILE] [-r REV] PATTERN [PATH]
search the working copy (rg) or another revision (jj file list/show);
scope non-@ greps with PATH, they read every file through jj
- vr note [-log FILE] [-r REV] [-f FILE[:START[-END]]] [-t KIND] TEXT...
+ vr note [-log FILE] [-r REV] [-f FILE[:START[-END]]] [-t KIND] [-reply NOTE] TEXT...
record a note about a file range or a kind of thing (struct, enum,
- const, ...); ids count up from 1 per session
+ const, ...), optionally replying to a log-wide note number; ids count
+ up from 1 per session
vr query [-log FILE] [-session S] [-op OP] [-file SUBSTR] [-n N]
print logged entries, oldest first
@@ -363,13 +365,20 @@ func cmdNote(args []string) {
rev := fs.String("r", "@", "jj revision the note refers to")
file := fs.String("f", "", "FILE[:START[-END]] the note is about")
kind := fs.String("t", "", "kind of thing the note is about (struct, enum, const, ...)")
+ reply := fs.Int("reply", 0, "log-wide note number this note replies to")
fs.Parse(args)
text := strings.Join(fs.Args(), " ")
if text == "" {
- fatal("usage: vr note [-log FILE] [-r REV] [-f FILE[:START[-END]]] [-t KIND] TEXT...")
+ fatal("usage: vr note [-log FILE] [-r REV] [-f FILE[:START[-END]]] [-t KIND] [-reply NOTE] TEXT...")
+ }
+ if *reply < 0 {
+ fatal("reply note must be positive")
+ }
+ if *reply > 0 && !hasNote(readLog(*logPath), *reply) {
+ fatal("no log-wide note #%d in %s", *reply, *logPath)
}
- e := Entry{Op: "note", Rev: *rev, Change: changeID(*rev), Type: *kind, Text: text}
+ e := Entry{Op: "note", Rev: *rev, Change: changeID(*rev), ReplyTo: *reply, Type: *kind, Text: text}
if *file != "" {
e.File, e.Start, e.End = parseFileRange(*file)
}
@@ -378,6 +387,21 @@ func cmdNote(args []string) {
fmt.Printf("note %d\n", e.NoteID)
}
+// hasNote uses the same numbering as vrsite permalinks: note operations count
+// from one over the append-only log, independent of their writers' sessions.
+func hasNote(entries []Entry, id int) bool {
+ n := 0
+ for _, e := range entries {
+ if e.Op == "note" {
+ n++
+ if n == id {
+ return true
+ }
+ }
+ }
+ return false
+}
+
func nextNoteID(logPath string) int {
max := 0
for _, e := range readLog(logPath) {
@@ -398,8 +422,16 @@ func cmdQuery(args []string) {
fs.Parse(args)
entries := readLog(*logPath)
- var kept []Entry
+ type result struct {
+ Entry
+ logNoteID int
+ }
+ var kept []result
+ logNoteID := 0
for _, e := range entries {
+ if e.Op == "note" {
+ logNoteID++
+ }
if *session != "" && !strings.Contains(e.Session, *session) {
continue
}
@@ -409,12 +441,13 @@ func cmdQuery(args []string) {
if *file != "" && !strings.Contains(e.File, *file) {
continue
}
- kept = append(kept, e)
+ kept = append(kept, result{Entry: e, logNoteID: logNoteID})
}
if *n > 0 && len(kept) > *n {
kept = kept[len(kept)-*n:]
}
- for _, e := range kept {
+ for _, r := range kept {
+ e := r.Entry
ts := e.Time
if t, err := time.Parse(time.RFC3339, e.Time); err == nil {
ts = t.Format("01-02 15:04:05")
@@ -438,7 +471,11 @@ func cmdQuery(args []string) {
if e.File != "" {
loc = " " + fileRange(e)
}
- fmt.Printf("%s #%d%s%s — %s\n", head, e.NoteID, tag, loc, e.Text)
+ rel := ""
+ if e.ReplyTo > 0 {
+ rel = fmt.Sprintf(" reply to log #%d", e.ReplyTo)
+ }
+ fmt.Printf("%s #%d [log #%d]%s%s%s — %s\n", head, e.NoteID, r.logNoteID, tag, loc, rel, e.Text)
default:
fmt.Printf("%s\n", head)
}