Skip to content

Commit

Permalink
Fix bugs with new note creation (#384)
Browse files Browse the repository at this point in the history
  • Loading branch information
epwalsh authored Feb 9, 2024
1 parent 649e559 commit a9e7fde
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 48 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Removed configuration option `detect_cwd`. This wasn't well-defined before and is no longer relevant with the new workspace detection behavior. See [PR #366](https://github.com/epwalsh/obsidian.nvim/pull/366).

### Fixed

- Fixed two bugs with creating new notes through `:ObsidianFollowLink` (and `gf`) where it wouldn't respect the `completion.new_notes_location` settings, and wouldn't respect paths in certain formats.

## [v2.10.0](https://github.com/epwalsh/obsidian.nvim/releases/tag/v2.10.0) - 2024-02-05

### Added
Expand Down
23 changes: 2 additions & 21 deletions lua/cmp_obsidian_new.lua
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
local abc = require "obsidian.abc"
local completion = require "obsidian.completion.refs"
local obsidian = require "obsidian"
local log = require "obsidian.log"
local NewNotesLocation = require("obsidian.config").CompletionNewNotesLocation
local LinkStyle = require("obsidian.config").LinkStyle

---@class cmp_obsidian_new.Source : obsidian.ABC
Expand All @@ -20,26 +18,10 @@ source.complete = function(_, request, callback)
local client = assert(obsidian.get_client())
local can_complete, search, insert_start, insert_end, ref_type = completion.can_complete(request)

---@type string|Path|?
local dir
if client.opts.completion.new_notes_location == nil then
dir = nil -- let the client decide
elseif client.opts.completion.new_notes_location == NewNotesLocation.notes_subdir then
dir = client.dir
if client.opts.notes_subdir ~= nil then
dir = dir / client.opts.notes_subdir
end
elseif client.opts.completion.new_notes_location == NewNotesLocation.current_dir then
dir = vim.fn.expand "%:p:h"
else
log.err "Bad option value for 'completion.new_notes_location'. Skipping creating new note."
return
end

if can_complete and search ~= nil and #search >= client.opts.completion.min_chars then
local new_title, new_id, path
new_id = client:new_note_id(search)
new_title, new_id, path = client:parse_title_id_path(search, new_id, dir)
new_title, new_id, path = client:parse_title_id_path(search, new_id)

if not new_title or string.len(new_title) == 0 then
return
Expand Down Expand Up @@ -81,7 +63,6 @@ source.complete = function(_, request, callback)
data = {
id = new_id,
title = search,
dir = dir,
},
},
}
Expand All @@ -98,7 +79,7 @@ end
source.execute = function(_, item, callback)
local client = assert(obsidian.get_client())
local data = item.data
client:new_note(data.title, data.id, data.dir)
client:new_note(data.title, data.id)
return callback {}
end

Expand Down
94 changes: 70 additions & 24 deletions lua/obsidian/client.lua
Original file line number Diff line number Diff line change
Expand Up @@ -931,48 +931,94 @@ end
---
---@return string|?,string,Path
Client.parse_title_id_path = function(self, title, id, dir)
---@type Path
local base_dir = dir == nil and self.dir or Path:new(dir)
local title_is_path = false
if title then
title = util.strip_whitespace(title)
if title == "" then
title = nil
end
end

if id then
id = util.strip_whitespace(id)
if id == "" then
id = nil
end
end

-- Clean up title and guess the right base_dir.
if title ~= nil then
-- Trim whitespace.
title = title:match "^%s*(.-)%s*$"
---@param s string
---@param strict_paths_only boolean
---@return string|?, boolean, string|?
local parse_as_path = function(s, strict_paths_only)
local is_path = false
---@type string|?
local parent

if title:match "%.md" then
if s:match "%.md" then
-- Remove suffix.
title = title:sub(1, title:len() - 3)
title_is_path = true
s = s:sub(1, s:len() - 3)
is_path = true
end

-- Pull out any parent dirs from title.
local parts = vim.split(title, Path.path.sep)
local parts = vim.split(s, Path.path.sep)
if #parts > 1 then
-- 'title' will just be the final part of the path.
title = parts[#parts]
-- Add the other parts to the base_dir.
base_dir = base_dir / table.concat(parts, Path.path.sep, 1, #parts - 1)
elseif dir == nil and self.opts.notes_subdir ~= nil then
base_dir = base_dir / self.opts.notes_subdir
s = parts[#parts]
if not strict_paths_only then
is_path = true
end
parent = table.concat(parts, Path.path.sep, 1, #parts - 1)
end

if s == "" then
return nil, is_path, parent
else
return s, is_path, parent
end
elseif dir == nil and self.opts.notes_subdir ~= nil then
base_dir = base_dir / self.opts.notes_subdir
end

if title == "" then
title = nil
local parent, _, title_is_path
if id then
id, _, parent = parse_as_path(id, false)
elseif title then
title, title_is_path, parent = parse_as_path(title, true)
if title_is_path then
id = title
end
end

---@type Path
local base_dir
if parent then
base_dir = self.dir / parent
else
local new_notes_location = self.opts.completion.new_notes_location
if not dir and new_notes_location then
if new_notes_location == config.CompletionNewNotesLocation.notes_subdir then
base_dir = self.dir
if self.opts.notes_subdir then
base_dir = base_dir / self.opts.notes_subdir
end
elseif new_notes_location == config.CompletionNewNotesLocation.current_dir then
base_dir = self.buf_dir and self.buf_dir or Path:new(vim.fs.dirname(vim.api.nvim_buf_get_name(0)))
else
error "Bad option value for 'completion.new_notes_location'. Skipping creating new note."
end
else
base_dir = Path:new(dir)
end
end

-- Generate new ID if needed.
local new_id = id and id or (title_is_path and title or self:new_note_id(title))
if not id then
id = self:new_note_id(title)
end

-- Get path.
---@type Path
---@diagnostic disable-next-line: assign-type-mismatch
local path = base_dir / (new_id .. ".md")
local path = base_dir / (id .. ".md")

return title, new_id, path
return title, id, path
end

--- Create and save a new note.
Expand Down
12 changes: 10 additions & 2 deletions lua/obsidian/commands/follow_link.lua
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,16 @@ return function(client, data)
})
if confirmation == "" or confirmation == "y" or confirmation == "yes" then
-- Create a new note.
local aliases = name == location and {} or { name }
note = client:new_note(location, nil, client.buf_dir, aliases)
---@type string|?, string[]
local id, aliases
if name == location then
aliases = {}
else
aliases = { name }
id = location
end

note = client:new_note(name, id, nil, aliases)
vim.api.nvim_command(open_cmd .. tostring(note.path))
else
log.warn "Aborting"
Expand Down
10 changes: 9 additions & 1 deletion test/obsidian/client_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,22 @@ describe("Client", function()
assert.is_false(saved_note.has_frontmatter)
end)

it("should parse a title that's a partial path", function()
it("should parse a title that's a partial path and generate new ID", function()
local client = tmp_client()
local title, id, path = client:parse_title_id_path "notes/Foo"
assert.equals(title, "Foo")
assert.equals(id, "foo")
assert.equals(tostring(path), tostring(Path:new(client.dir) / "notes" / "foo.md"))
end)

it("should parse an ID that's a path", function()
local client = tmp_client()
local title, id, path = client:parse_title_id_path("Foo", "notes/1234-foo")
assert.equals(title, "Foo")
assert.equals(id, "1234-foo")
assert.equals(tostring(path), tostring(Path:new(client.dir) / "notes" / "1234-foo.md"))
end)

it("should parse a title that's an exact path", function()
local client = tmp_client()
local title, id, path = client:parse_title_id_path "notes/foo.md"
Expand Down

0 comments on commit a9e7fde

Please sign in to comment.