From 56486e1dfd4cb7803e11fc3aa7798514991a5f07 Mon Sep 17 00:00:00 2001 From: Pete Date: Wed, 12 Oct 2022 16:57:28 -0700 Subject: [PATCH] Improve completion, make less sensitive to case (#33) * improve completion * clean up --- CHANGELOG.md | 4 +++ lua/cmp_obsidian.lua | 50 ++++++++++++++++++++++++------------- lua/obsidian/command.lua | 2 +- lua/obsidian/init.lua | 6 +++-- lua/obsidian/util.lua | 23 ++++++++++++++++- test/obsidian/util_spec.lua | 4 +++ 6 files changed, 68 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c34199d3..2e5e3e40f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Fixed + +- Fixed autocomplete functionality to be less sensitive to case. + ## [v1.5.0](https://github.com/epwalsh/obsidian.nvim/releases/tag/v1.5.0) - 2022-10-12 ### Changed diff --git a/lua/cmp_obsidian.lua b/lua/cmp_obsidian.lua index fa59a1da1..a7afc736e 100644 --- a/lua/cmp_obsidian.lua +++ b/lua/cmp_obsidian.lua @@ -1,6 +1,7 @@ local completion = require "obsidian.completion" local obsidian = require "obsidian" local config = require "obsidian.config" +local util = require "obsidian.util" local source = {} @@ -19,26 +20,41 @@ source.complete = function(self, request, callback) if can_complete and search ~= nil and #search >= opts.completion.min_chars then local items = {} - for note in client:search(search) do + for note in client:search(search, "--ignore-case") do for _, alias in pairs(note.aliases) do - table.insert(items, { - sortText = "[[" .. alias, - label = "[[" .. note.id .. "|" .. alias .. "]]", - kind = 18, - textEdit = { - newText = "[[" .. note.id .. "|" .. alias .. "]]", - insert = { - start = { - line = request.context.cursor.row - 1, - character = insert_start, - }, - ["end"] = { - line = request.context.cursor.row - 1, - character = insert_end, + local options = {} + + local alias_case_matched = util.match_case(search, alias) + if + alias_case_matched ~= nil + and alias_case_matched ~= alias + and not util.contains(note.aliases, alias_case_matched) + then + table.insert(options, alias_case_matched) + end + + table.insert(options, alias) + + for _, option in pairs(options) do + table.insert(items, { + sortText = "[[" .. option, + label = "[[" .. note.id .. "|" .. option .. "]]", + kind = 18, + textEdit = { + newText = "[[" .. note.id .. "|" .. option .. "]]", + insert = { + start = { + line = request.context.cursor.row - 1, + character = insert_start, + }, + ["end"] = { + line = request.context.cursor.row - 1, + character = insert_end, + }, }, }, - }, - }) + }) + end end end return callback { diff --git a/lua/obsidian/command.lua b/lua/obsidian/command.lua index eeaae3b48..2b316fa8a 100644 --- a/lua/obsidian/command.lua +++ b/lua/obsidian/command.lua @@ -131,7 +131,7 @@ end ---@param client obsidian.Client ---@param data table command.search = function(client, data) - local base_cmd = vim.tbl_flatten { util.SEARCH_CMD, { "--column", "--line-number", "--no-heading" } } + local base_cmd = vim.tbl_flatten { util.SEARCH_CMD, { "--smart-case", "--column", "--line-number", "--no-heading" } } local has_telescope, telescope = pcall(require, "telescope.builtin") diff --git a/lua/obsidian/init.lua b/lua/obsidian/init.lua index 03827d541..4446cc32f 100644 --- a/lua/obsidian/init.lua +++ b/lua/obsidian/init.lua @@ -137,9 +137,11 @@ end ---Search for notes. Returns an iterator over matching notes. --- ---@param search string +---@param opts string ---@return function -client.search = function(self, search) - local search_results = obsidian.util.search(self.dir, search, "-m 1") +client.search = function(self, search, opts) + opts = opts and (opts .. " ") or "" + local search_results = obsidian.util.search(self.dir, search, opts .. "-m 1") ---@return obsidian.Note|? return function() diff --git a/lua/obsidian/util.lua b/lua/obsidian/util.lua index af44872fa..abdd8fa44 100644 --- a/lua/obsidian/util.lua +++ b/lua/obsidian/util.lua @@ -55,7 +55,7 @@ util.urlencode = function(str) return url end -util.SEARCH_CMD = { "rg", "--no-config", "--smart-case", "--fixed-strings", "--type=md" } +util.SEARCH_CMD = { "rg", "--no-config", "--fixed-strings", "--type=md" } ---@class MatchPath ---@field text string @@ -121,4 +121,25 @@ util.zettel_id = function() return tostring(os.time()) .. "-" .. suffix end +---Match the case of 'key' to the given 'prefix' of the key. +--- +---@param prefix string +---@param key string +---@return string|? +util.match_case = function(prefix, key) + local out_chars = {} + for i = 1, string.len(key) do + local c_key = string.sub(key, i, i) + local c_pre = string.sub(prefix, i, i) + if c_pre:lower() == c_key:lower() then + table.insert(out_chars, c_pre) + elseif c_pre:len() > 0 then + return nil + else + table.insert(out_chars, c_key) + end + end + return table.concat(out_chars, "") +end + return util diff --git a/test/obsidian/util_spec.lua b/test/obsidian/util_spec.lua index 02fbcb00b..e0e49ee97 100644 --- a/test/obsidian/util_spec.lua +++ b/test/obsidian/util_spec.lua @@ -4,4 +4,8 @@ describe("obsidian.util", function() it("should correctly URL-encode a path", function() assert.equals(util.urlencode [[~/Library/Foo Bar.md]], [[~%2FLibrary%2FFoo+Bar.md]]) end) + it("should match case of key to prefix", function() + assert.equals(util.match_case("Foo", "foo"), "Foo") + assert.equals(util.match_case("In-cont", "in-context learning"), "In-context learning") + end) end)