Skip to content

Commit b0fd116

Browse files
authored
Add new client and note methods (#351)
1 parent 64de405 commit b0fd116

File tree

5 files changed

+77
-15
lines changed

5 files changed

+77
-15
lines changed

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## Unreleased
99

10+
### Added
11+
12+
- Added client method `Client:current_note()` to get the note corresponding to the current buffer.
13+
- Added note method `Note.add_field(key: string, value: any)` to add/update an additional field in the frontmatter.
14+
- Added note method ` Note.save_to_buffer(bufnr: integer|?, frontmatter: table|?)` for saving the frontmatter to a buffer.
15+
1016
## [v2.8.0](https://github.com/epwalsh/obsidian.nvim/releases/tag/v2.8.0) - 2024-01-26
1117

1218
### Added

lua/obsidian/client.lua

+11
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,17 @@ Client.resolve_note_async = function(self, query, callback)
550550
end)
551551
end
552552

553+
--- Get the current note.
554+
---
555+
---@return obsidian.Note|?
556+
Client.current_note = function(self)
557+
if vim.bo.filetype ~= "markdown" then
558+
return nil
559+
end
560+
561+
return Note.from_buffer(0, self.dir)
562+
end
563+
553564
---@class obsidian.TagLocation
554565
---
555566
---@field tag string The tag found.

lua/obsidian/init.lua

+2-13
Original file line numberDiff line numberDiff line change
@@ -225,20 +225,9 @@ obsidian.setup = function(opts)
225225
if client.opts.note_frontmatter_func ~= nil then
226226
frontmatter = client.opts.note_frontmatter_func(note)
227227
end
228-
local new_lines = note:frontmatter_lines(nil, frontmatter)
229-
local cur_lines
230-
if note.frontmatter_end_line ~= nil then
231-
cur_lines = vim.api.nvim_buf_get_lines(0, 0, note.frontmatter_end_line, false)
232-
end
233228

234-
vim.api.nvim_buf_set_lines(
235-
bufnr,
236-
0,
237-
note.frontmatter_end_line and note.frontmatter_end_line or 0,
238-
false,
239-
new_lines
240-
)
241-
if not client._quiet and not vim.deep_equal(cur_lines, new_lines) then
229+
local updated = note:save_to_buffer(bufnr, frontmatter)
230+
if not client._quiet and updated then
242231
log.info "Updated frontmatter"
243232
end
244233
end,

lua/obsidian/note.lua

+47-2
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,22 @@ Note.add_tag = function(self, tag)
132132
end
133133
end
134134

135+
--- Add or update a field in the frontmatter.
136+
---
137+
---@param key string
138+
---@param value any
139+
Note.add_field = function(self, key, value)
140+
if key == "id" or key == "aliases" or key == "tags" then
141+
error "Updating field '%s' this way is not allowed. Please update the corresponding attribute directly instead"
142+
end
143+
144+
if not self.metadata then
145+
self.metadata = {}
146+
end
147+
148+
self.metadata[key] = value
149+
end
150+
135151
--- Initialize a note from a file.
136152
---
137153
---@param path string|Path
@@ -447,7 +463,7 @@ Note.frontmatter_lines = function(self, eol, frontmatter)
447463
end
448464
end
449465

450-
--- Save note to file.
466+
--- Save note to file. This only updates the frontmatter and header, leaving the rest of the contents unchanged.
451467
---
452468
---@param path string|Path|?
453469
---@param insert_frontmatter boolean|?
@@ -467,7 +483,8 @@ Note.save = function(self, path, insert_frontmatter, frontmatter)
467483
if self_f ~= nil then
468484
local contents = self_f:read "*a"
469485
for idx, line in ipairs(vim.split(contents, "\n")) do
470-
table.insert(lines, line .. "\n")
486+
lines[#lines + 1] = line .. "\n"
487+
471488
if idx == 1 then
472489
if Note._is_frontmatter_boundary(line) then
473490
has_frontmatter = true
@@ -480,6 +497,7 @@ Note.save = function(self, path, insert_frontmatter, frontmatter)
480497
end
481498
end
482499
end
500+
483501
self_f:close()
484502
elseif #self.aliases > 0 then
485503
-- Add a header.
@@ -512,4 +530,31 @@ Note.save = function(self, path, insert_frontmatter, frontmatter)
512530
return lines
513531
end
514532

533+
--- Save frontmatter to the given buffer.
534+
---
535+
---@param bufnr integer|?
536+
---@param frontmatter table|?
537+
---
538+
---@return boolean updated True if the buffer lines were updated, false otherwise.
539+
Note.save_to_buffer = function(self, bufnr, frontmatter)
540+
bufnr = bufnr and bufnr or 0
541+
542+
local cur_buf_note = Note.from_buffer(bufnr)
543+
local new_lines = self:frontmatter_lines(nil, frontmatter)
544+
local cur_lines
545+
if cur_buf_note.frontmatter_end_line ~= nil then
546+
cur_lines = vim.api.nvim_buf_get_lines(bufnr, 0, cur_buf_note.frontmatter_end_line, false)
547+
end
548+
549+
vim.api.nvim_buf_set_lines(
550+
bufnr,
551+
0,
552+
cur_buf_note.frontmatter_end_line and cur_buf_note.frontmatter_end_line or 0,
553+
false,
554+
new_lines
555+
)
556+
557+
return not vim.deep_equal(cur_lines, new_lines)
558+
end
559+
515560
return Note

test/obsidian/note_spec.lua

+11
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ describe("Note", function()
99
assert.equals(note.id, "FOO")
1010
assert.equals(note.aliases[1], "foo")
1111
end)
12+
1213
it("should be able to be initialized from a file", function()
1314
local note = Note.from_file "test_fixtures/notes/foo.md"
1415
assert.equals(note.id, "foo")
@@ -18,13 +19,15 @@ describe("Note", function()
1819
assert.is_true(note.has_frontmatter)
1920
assert(#note.tags == 0)
2021
end)
22+
2123
it("should be able to be initialized from a README", function()
2224
local note = Note.from_file "README.md"
2325
assert.equals(note.id, "README")
2426
assert.equals(#note.tags, 0)
2527
assert.equals(note:fname(), "README.md")
2628
assert.is_false(note:should_save_frontmatter())
2729
end)
30+
2831
it("should be able to be initialized from a note w/o frontmatter", function()
2932
local note = Note.from_file "test_fixtures/notes/note_without_frontmatter.md"
3033
assert.equals(note.id, "note_without_frontmatter")
@@ -35,32 +38,39 @@ describe("Note", function()
3538
assert.is_false(note.has_frontmatter)
3639
assert.is_true(note:should_save_frontmatter())
3740
end)
41+
3842
it("should be able to add an alias", function()
3943
local note = Note.from_file "test_fixtures/notes/foo.md"
4044
assert.equals(#note.aliases, 2)
4145
note:add_alias "Foo Bar"
4246
assert.equals(#note.aliases, 3)
4347
end)
48+
4449
it("should be able to save to file", function()
4550
local note = Note.from_file "test_fixtures/notes/foo.md"
4651
note:add_alias "Foo Bar"
4752
note:save "./test_fixtures/notes/foo_bar.md"
4853
end)
54+
4955
it("should be able to save note w/o frontmatter to file", function()
5056
local note = Note.from_file "test_fixtures/notes/note_without_frontmatter.md"
5157
note:save "./test_fixtures/notes/note_without_frontmatter_saved.md"
5258
end)
59+
5360
it("should be able to save a new note", function()
5461
local note = Note.new("FOO", {}, {}, "/tmp/" .. util.zettel_id() .. ".md")
5562
note:save()
5663
end)
64+
5765
it("should be able to parse a markdown header", function()
5866
assert.equals(Note._parse_header "## Hey there", "Hey there")
5967
end)
68+
6069
it("should be able to find a frontmatter boundary", function()
6170
assert.is_true(Note._is_frontmatter_boundary "---")
6271
assert.is_true(Note._is_frontmatter_boundary "----")
6372
end)
73+
6474
it("should be able to be initialize and save a note with additional frontmatter metadata", function()
6575
local note = Note.from_file "test_fixtures/notes/note_with_additional_metadata.md"
6676
assert.equals(note.id, "note_with_additional_metadata")
@@ -80,6 +90,7 @@ describe("Note", function()
8090
)
8191
note:save "./test_fixtures/notes/note_with_additional_metadata_saved.md"
8292
end)
93+
8394
it("should be able to be read frontmatter that's formatted differently", function()
8495
local note = Note.from_file "test_fixtures/notes/note_with_different_frontmatter_format.md"
8596
assert.equals(note.id, "note_with_different_frontmatter_format")

0 commit comments

Comments
 (0)