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
20 changes: 13 additions & 7 deletions .mise/tasks/list
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,19 @@ elif not rows:
else:
print("No notes found.")
else:
def _sanitize(val: str) -> str:
return str(val).replace("\t", " ").replace("\n", "⏎")

table = "Title\tType\tStatus\tTags\tUpdated\n" + "\n".join(
f"{row['title']}\t{row['type']}\t{row['status']}\t{', '.join(row['tags'])}\t{row['date']}" for row in rows
)
subprocess.run(
["gum", "table", "--print", "--separator", "\t"],
input=table,
text=True,
check=True,
f"{_sanitize(row['title'])}\t{_sanitize(row['type'])}\t{_sanitize(row['status'])}\t{_sanitize(', '.join(row['tags']))}\t{_sanitize(row['date'])}" for row in rows
)
try:
subprocess.run(
["gum", "table", "--print", "--separator", "\t"],
input=table,
text=True,
check=True,
)
except (subprocess.CalledProcessError, FileNotFoundError):
print(table)
PY
20 changes: 13 additions & 7 deletions .mise/tasks/search
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,19 @@ elif not rows:
suffix = f" with {' '.join(filters)}" if filters else ""
print(f"No notes found matching: {query}{suffix}")
else:
def _sanitize(val: str) -> str:
return str(val).replace("\t", " ").replace("\n", "⏎")

table = "Title\tType\tStatus\tUpdated\tMatches\n" + "\n".join(
f"{row['title']}\t{row['type']}\t{row['status']}\t{row['date']}\t{' | '.join(row['matches'][:2])}" for row in rows
)
subprocess.run(
["gum", "table", "--print", "--separator", "\t"],
input=table,
text=True,
check=True,
f"{_sanitize(row['title'])}\t{_sanitize(row['type'])}\t{_sanitize(row['status'])}\t{_sanitize(row['date'])}\t{_sanitize(' | '.join(row['matches'][:2]))}" for row in rows
)
try:
subprocess.run(
["gum", "table", "--print", "--separator", "\t"],
input=table,
text=True,
check=True,
)
except (subprocess.CalledProcessError, FileNotFoundError):
print(table)
PY
30 changes: 30 additions & 0 deletions test/search.bats
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,33 @@ EOF
[ "$status" -eq 0 ]
[[ "$output" == *"No notes found matching: absent"* ]]
}

@test "search falls back to TSV when gum table rejects unusual characters" {
# Write a note with a literal tab in the title — this breaks gum table's TSV parser
python3 << 'PYEND'
import os
path = os.path.join(os.environ['NOTES_CALLER_PWD'], 'notes', 'unusual.md')
content = (
'---\n'
'title: "Tab\tTitle"\n'
'type: note\n'
'status: active\n'
'tags: [test]\n'
'created: 2026-01-01\n'
'updated: 2026-01-02\n'
'---\n'
'\n'
'# Tab\tTitle\n'
'Body with\ta\ttab\ttoo.\n'
)
with open(path, 'w') as f:
f.write(content)
PYEND

run notes search Tab
[ "$status" -eq 0 ]
# Should get sanitized output (tabs → spaces), not a crash
echo "$output" | grep -q "Tab Title"
# Body match snippet found (matches[:2] limits display, but first body line is enough)
echo "$output" | grep -q "# Tab Title"
}