Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,28 @@ That’s the point.

---

## templates

Seed a note with a developer template:

```bash
jot new --template incident
```

Available templates:

* `incident`
* `meeting`
* `rfc`

### contributing templates

1. Add a new markdown file in `templates/` with a short, lowercase name (e.g. `templates/retro.md`).
2. Keep templates lightweight and fill-in-the-blank.
3. Update this README to list the new template name.

---

## what should I write?

If you’re unsure, start here:
Expand Down
60 changes: 59 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"bufio"
"embed"
"errors"
"fmt"
"io"
Expand All @@ -13,6 +14,9 @@ import (

const version = "1.5.1"

//go:embed templates/*.md
var templatesFS embed.FS

func main() {
_ = version

Expand All @@ -38,7 +42,15 @@ func main() {
return
}

fmt.Fprintln(os.Stderr, "usage: jot [init|list|patterns]")
if len(args) >= 1 && args[0] == "new" {
if err := jotNew(os.Stdout, args[1:]); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
return
}

fmt.Fprintln(os.Stderr, "usage: jot [init|list|patterns|new --template <name>]")
os.Exit(1)
}

Expand Down Expand Up @@ -179,3 +191,49 @@ func isTTY(w io.Writer) bool {
}
return (info.Mode() & os.ModeCharDevice) != 0
}

func jotNew(w io.Writer, args []string) error {
templateName, err := parseTemplateArg(args)
if err != nil {
return err
}

return writeTemplate(w, templateName)
}

func parseTemplateArg(args []string) (string, error) {
var templateName string

for i := 0; i < len(args); i++ {
arg := args[i]
switch {
case arg == "--template" || arg == "-t":
if i+1 >= len(args) {
return "", errors.New("template name required after --template")
}
templateName = args[i+1]
i++
case strings.HasPrefix(arg, "--template="):
templateName = strings.TrimPrefix(arg, "--template=")
default:
return "", fmt.Errorf("unknown argument: %s", arg)
}
}

if templateName == "" {
return "", errors.New("template required: use --template <name>")
}

return templateName, nil
}

func writeTemplate(w io.Writer, templateName string) error {
path := filepath.ToSlash(filepath.Join("templates", templateName+".md"))
data, err := templatesFS.ReadFile(path)
if err != nil {
return fmt.Errorf("unknown template %q", templateName)
}

_, err = w.Write(data)
return err
}
24 changes: 24 additions & 0 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"bytes"
"os"
"path/filepath"
"runtime"
"strings"
"testing"
Expand Down Expand Up @@ -123,3 +124,26 @@ func TestJotInitAppendsWithTimestamp(t *testing.T) {
t.Fatalf("expected entry %q, got %q", expectedEntry, string(data))
}
}

func TestJotNewWritesTemplate(t *testing.T) {
expected, err := os.ReadFile(filepath.Join("templates", "incident.md"))
if err != nil {
t.Fatalf("read template failed: %v", err)
}

var out bytes.Buffer
if err := jotNew(&out, []string{"--template", "incident"}); err != nil {
t.Fatalf("jotNew returned error: %v", err)
}

if out.String() != string(expected) {
t.Fatalf("expected template output to match file contents")
}
}

func TestJotNewRejectsUnknownTemplate(t *testing.T) {
var out bytes.Buffer
if err := jotNew(&out, []string{"--template", "unknown"}); err == nil {
t.Fatalf("expected error for unknown template")
}
}
28 changes: 28 additions & 0 deletions templates/incident.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Incident Report

**Incident ID:**
**Date:**
**Owner:**
**Status:**

## Summary

## Impact
- Users affected:
- Duration:
- Severity:

## Timeline
-

## Detection

## Root Cause

## Resolution & Recovery

## Action Items
- [ ]

## Learnings

21 changes: 21 additions & 0 deletions templates/meeting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Meeting Notes

**Date:**
**Time:**
**Facilitator:**
**Attendees:**

## Agenda
-

## Discussion Notes
-

## Decisions
-

## Action Items
- [ ]

## Follow-ups
-
31 changes: 31 additions & 0 deletions templates/rfc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# RFC: <Title>

**Status:** Draft
**Author(s):**
**Created:**
**Last Updated:**

## Summary

## Motivation

## Goals
-

## Non-Goals
-

## Proposal

## Alternatives Considered
-

## Risks & Mitigations
-

## Rollout Plan
-

## Open Questions
-