-
-
Notifications
You must be signed in to change notification settings - Fork 142
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(core): enhance org-insert-link, add completion for ~/
prefix.
#749
feat(core): enhance org-insert-link, add completion for ~/
prefix.
#749
Conversation
Yeah, the autocompletion for We try to collect all link-related string matchings in |
69896b7
to
539a3f1
Compare
Thanks for your reply and guidance. And I will fix the failed test later. I did it in this way: So the completion logic is simplified. |
87800bb
to
99d8313
Compare
@seflue Hi Sebastian, I have done the refactoration. Could you take a review if convenient? |
I manually tested it and this was the result:
So while your targeted test case for the home path Problem: All tests are still green, so we need to improve our test coverage to catch (and fix) the regression. If you plan on adding the relative path in a later PR, thats ok for me. Even if you fix the regression by manually testing it that would be fine for this PR (although I would very appreciate, if we can use this opportunity to cover these cases with tests). But at least the regression needs to be fixed. |
Thanks for the feedback. As for the results, I am not sure how you tested it. I tested it in 2 ways : (a)
The behavior is caused by |
I actually did only test |
I tested again and now it works for me. Great work! Please consider my code comment. |
That sounds good to me! BTW, what does the code comment mean here? I did not see code comments in the review. I found it hard for me to write the tests (lol, as a newbie to the code structure) The completion triggers cmp instead of omni, so there is little code for reference. Do you have any suggestions about how to build the unit test? |
You can't see my review comment I directly add to your changes? It should actually be visible within this conversation, but you can also switch to the "Files changed" tab and scroll down until you see a comment. I annotated your changes to
Don't worry, it's the same for me. It's not easy to get a hang of how to implement such tests and there might be a reason why these code parts are currently not covered. Because your changes already bring a lot of value, I would prefer for the time being to just rename the flag, merge this PR and create further PRs for improvements and test cases. |
Regarding the tests, did you already found |
Seems still no comments are viewable. Not sure what happened : /
Maybe I can contribute to the further test coverage in a few weeks. :) |
Yes, I did some tests on this file and it's omni-pure. I would refer to it when building the nvim-cmp completion test. |
How the omni completion in hyperlinks are tested, you can see here: orgmode/tests/plenary/org/autocompletion_spec.lua Lines 86 to 136 in cc51c19
Adding some test cases, which cover |
My fault, I forgot to submit the review. Is it now visible for you? |
lua/orgmode/utils/fs.lua
Outdated
@@ -21,7 +21,7 @@ function M.substitute_path(path_str) | |||
end | |||
|
|||
---@param filepath string | |||
function M.get_real_path(filepath) | |||
function M.get_real_path(filepath, match) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I'm not a big fan of flags like these.
Questions, which come up here: Why make keeping the trailing slash optional? If the path has a trailing slash, why should it be removed? Can we make keeping it default behavior?
And if we can't, we should at least name the flag keep_trailing_slash
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems no other affect on tests, so I will remove the flag.
As I am stepping through this testfile, I now remember, that these tests just find the correct start for completion, while the actual completion is done when passing Here we're still very short on test cases for file paths. |
I found the omnifunc is also available, and I did not find it before because I used cmp by default. So maybe cmp test is not needed for now. |
lua/orgmode/utils/fs.lua
Outdated
@@ -30,11 +30,8 @@ function M.get_real_path(filepath, match) | |||
return false | |||
end | |||
local real = vim.loop.fs_realpath(substituted) | |||
if match then | |||
-- if path ends with / , real needs too |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I find the comment useful and would not remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure.
it('should work on relative paths', function()
local function load_file(path)
local orgmode = require("orgmode")
print('loading ' .. path or '')
vim.cmd(string.format('e %s', path))
return orgmode.files:get(path)
end
local files = helpers.create_agenda_files({
"a.org",
"b/c.org"
}, {
"[[./ ",
"[[../ "
})
local utils = require("orgmode.utils")
load_file(files["a.org"])
vim.fn.cursor({ 1, 5 })
local result = org.completion:omnifunc(0, './')
assert.are.same({
{ menu = '[Org]', word = './a.org' },
{ menu = '[Org]', word = './b/c.org' },
}, result)
load_file(files["b/c.org"])
vim.fn.cursor({ 1, 6 })
local result = org.completion:omnifunc(0, '../')
assert.are.same({
{ menu = '[Org]', word = '../a.org' },
{ menu = '[Org]', word = '../b/c.org' },
}, result)
end) I made up some naive test on it, and it worked. I wonder if you prefer a new pr or just continue it on this thread. the commit: a5b1f73 |
… or ~/ _squash: keep Url.path, and add a realpath filed fix: make sure realpath and path's ends are matched e.g. /path/to/me ../to/me /path/to/me/ ../to/me/ refactor: remove unused flag refactor: add comments on trailing slash _fix
fb38b94
to
091ea76
Compare
As you are just continued to work on the tests, we can include these into this PR. I mentioned a separate PR just because you wrote:
|
Would you mind to split the two test cases for |
|
'b/c.org', | ||
}, { | ||
'[[./ ', | ||
'[[../ ', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't want to be a nitpick, but I would prefer to clean each test a bit up to be specific for the case. Makes it easier for future contributions to not be distracted by code, which is actually irrelevant for the test case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with you.
The case here is mainly about paths, so the content does not really matter. So do you suggest me to add some extra info to the files?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I had a misconception, how the create_agenda_files
function works. The position in the file table corresponds with the position in the content table.
So I think, this cannot be improved further with reasonable amount of effort.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fine, so we just keep it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also see now, that you contributed this function - I thought it already existed.
I have actually one last improvement: Can you change the interface of the function in that way, that it takes a list of tables, each one for each agenda file. And that each entry in this table is again an associative table with the keys filename
and content
. While filename is just a string, content
would be again a table, each entry a line. This makes your function reusable for more complicated use cases with multiline content for an agenda file. I already have several test cases in mind, where this might be very useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And sorry for the inconvenience, I use the review functions of Github actually the first time and just found the "Review in workspace" feature, which is actually great. Wished I found it earlier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my side everything is good now. Thanks a lot for this contribution!
:) Thanks for your kind guidance |
'b/c.org', | ||
}, { | ||
'[[./ ', | ||
'[[../ ', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also see now, that you contributed this function - I thought it already existed.
I have actually one last improvement: Can you change the interface of the function in that way, that it takes a list of tables, each one for each agenda file. And that each entry in this table is again an associative table with the keys filename
and content
. While filename is just a string, content
would be again a table, each entry a line. This makes your function reusable for more complicated use cases with multiline content for an agenda file. I already have several test cases in mind, where this might be very useful.
'b/c.org', | ||
}, { | ||
'[[./ ', | ||
'[[../ ', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And sorry for the inconvenience, I use the review functions of Github actually the first time and just found the "Review in workspace" feature, which is actually great. Wished I found it earlier.
---@return table | ||
local function create_agenda_files(filenames, contents) | ||
-- NOTE: content is only 1 line for 1 file | ||
local temp_fname = vim.fn.tempname() | ||
local temp_dir = vim.fn.fnamemodify(temp_fname, ':p:h') | ||
-- clear temp dir | ||
vim.fn.delete(temp_dir .. '/*', 'rf') | ||
local files = {} | ||
local agenda_files = {} | ||
for i, filename in ipairs(filenames) do | ||
local fname = temp_dir .. '/' .. filename | ||
fname = vim.fn.fnamemodify(fname, ':p') | ||
if fname then | ||
local dir = vim.fn.fnamemodify(fname, ':p:h') | ||
vim.fn.mkdir(dir, 'p') | ||
vim.fn.writefile({ contents[i] }, fname) | ||
files[filename] = fname | ||
table.insert(agenda_files, fname) | ||
end | ||
end | ||
local cfg = vim.tbl_extend('force', { | ||
org_agenda_files = agenda_files, | ||
}, {}) | ||
local org = orgmode.setup(cfg) | ||
org:init() | ||
return files | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
---@return table | |
local function create_agenda_files(filenames, contents) | |
-- NOTE: content is only 1 line for 1 file | |
local temp_fname = vim.fn.tempname() | |
local temp_dir = vim.fn.fnamemodify(temp_fname, ':p:h') | |
-- clear temp dir | |
vim.fn.delete(temp_dir .. '/*', 'rf') | |
local files = {} | |
local agenda_files = {} | |
for i, filename in ipairs(filenames) do | |
local fname = temp_dir .. '/' .. filename | |
fname = vim.fn.fnamemodify(fname, ':p') | |
if fname then | |
local dir = vim.fn.fnamemodify(fname, ':p:h') | |
vim.fn.mkdir(dir, 'p') | |
vim.fn.writefile({ contents[i] }, fname) | |
files[filename] = fname | |
table.insert(agenda_files, fname) | |
end | |
end | |
local cfg = vim.tbl_extend('force', { | |
org_agenda_files = agenda_files, | |
}, {}) | |
local org = orgmode.setup(cfg) | |
org:init() | |
return files | |
end | |
---@param agenda_file {filename: string, content: string[] }[] | |
---@return table | |
local function create_agenda_files(fixtures) | |
-- NOTE: content is only 1 line for 1 file | |
local temp_fname = vim.fn.tempname() | |
local temp_dir = vim.fn.fnamemodify(temp_fname, ':p:h') | |
-- clear temp dir | |
vim.fn.delete(temp_dir .. '/*', 'rf') | |
local files = {} | |
local agenda_files = {} | |
for fixture in pairs(fixtures) do | |
local fname = temp_dir .. '/' .. fixture.filename | |
fname = vim.fn.fnamemodify(fname, ':p') | |
if fname then | |
local dir = vim.fn.fnamemodify(fname, ':p:h') | |
vim.fn.mkdir(dir, 'p') | |
vim.fn.writefile(fixture.content, fname) | |
files[filename] = fname | |
table.insert(agenda_files, fname) | |
end | |
end | |
local cfg = vim.tbl_extend('force', { | |
org_agenda_files = agenda_files, | |
}, {}) | |
local org = orgmode.setup(cfg) | |
org:init() | |
return files | |
end |
This is, what I imagine as the modified interface of the helper function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with @seflue on this. We can also add the 2nd parameter to be config, the same way we have it for create_agenda_file
.
local files = helpers.create_agenda_files({ | ||
'a.org', | ||
'b/c.org', | ||
}, { | ||
'[[./ ', | ||
'[[../ ', | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
local files = helpers.create_agenda_files({ | |
'a.org', | |
'b/c.org', | |
}, { | |
'[[./ ', | |
'[[../ ', | |
}) | |
local files = helpers.create_agenda_files({ | |
{ | |
filename = 'a.org', | |
content = { {'[[./'}}, | |
}, | |
{ | |
filename = 'b.org', | |
content = {} | |
} | |
}) |
More specific test case B.
local files = helpers.create_agenda_files({ | ||
'a.org', | ||
'b/c.org', | ||
}, { | ||
'[[./ ', | ||
'[[../ ', | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
local files = helpers.create_agenda_files({ | |
'a.org', | |
'b/c.org', | |
}, { | |
'[[./ ', | |
'[[../ ', | |
}) | |
local files = helpers.create_agenda_files({ | |
{ | |
filename = 'a.org', | |
content = {}, | |
}, | |
{ | |
filename = 'b.org', | |
content = { {'[[../'} } | |
} |
More specific test case A.
@kristijanhusak I think, we can merge this PR, I can also make the small cosmetic changes myself. Just a question: Are you the only person, who can approve PRs? My approval does not remove the merge block. |
Thanks for the edition, I didn't check mails today. lol
…---Original---
From: "Sebastian ***@***.***>
Date: Sun, Jun 16, 2024 17:20 PM
To: ***@***.***>;
Cc: "Yunqian ***@***.******@***.***>;
Subject: Re: [nvim-orgmode/orgmode] feat(core): enhance org-insert-link, addcompletion for `~/` prefix. (PR #749)
@seflue approved this pull request.
In tests/plenary/helpers.lua:
> ***@***.*** table +local function create_agenda_files(filenames, contents) + -- NOTE: content is only 1 line for 1 file + local temp_fname = vim.fn.tempname() + local temp_dir = vim.fn.fnamemodify(temp_fname, ':p:h') + -- clear temp dir + vim.fn.delete(temp_dir .. '/*', 'rf') + local files = {} + local agenda_files = {} + for i, filename in ipairs(filenames) do + local fname = temp_dir .. '/' .. filename + fname = vim.fn.fnamemodify(fname, ':p') + if fname then + local dir = vim.fn.fnamemodify(fname, ':p:h') + vim.fn.mkdir(dir, 'p') + vim.fn.writefile({ contents[i] }, fname) + files[filename] = fname + table.insert(agenda_files, fname) + end + end + local cfg = vim.tbl_extend('force', { + org_agenda_files = agenda_files, + }, {}) + local org = orgmode.setup(cfg) + org:init() + return files +end ⬇️ Suggested change ***@***.*** table -local function create_agenda_files(filenames, contents) - -- NOTE: content is only 1 line for 1 file - local temp_fname = vim.fn.tempname() - local temp_dir = vim.fn.fnamemodify(temp_fname, ':p:h') - -- clear temp dir - vim.fn.delete(temp_dir .. '/*', 'rf') - local files = {} - local agenda_files = {} - for i, filename in ipairs(filenames) do - local fname = temp_dir .. '/' .. filename - fname = vim.fn.fnamemodify(fname, ':p') - if fname then - local dir = vim.fn.fnamemodify(fname, ':p:h') - vim.fn.mkdir(dir, 'p') - vim.fn.writefile({ contents[i] }, fname) - files[filename] = fname - table.insert(agenda_files, fname) - end - end - local cfg = vim.tbl_extend('force', { - org_agenda_files = agenda_files, - }, {}) - local org = orgmode.setup(cfg) - org:init() - return files -end ***@***.*** agenda_file {filename: string, content: string[] }[] ***@***.*** table +local function create_agenda_files(fixtures) + -- NOTE: content is only 1 line for 1 file + local temp_fname = vim.fn.tempname() + local temp_dir = vim.fn.fnamemodify(temp_fname, ':p:h') + -- clear temp dir + vim.fn.delete(temp_dir .. '/*', 'rf') + local files = {} + local agenda_files = {} + for fixture in pairs(fixtures) do + local fname = temp_dir .. '/' .. fixture.filename + fname = vim.fn.fnamemodify(fname, ':p') + if fname then + local dir = vim.fn.fnamemodify(fname, ':p:h') + vim.fn.mkdir(dir, 'p') + vim.fn.writefile(fixture.content, fname) + files[filename] = fname + table.insert(agenda_files, fname) + end + end + local cfg = vim.tbl_extend('force', { + org_agenda_files = agenda_files, + }, {}) + local org = orgmode.setup(cfg) + org:init() + return files +end
This is, what I imagine as the modified interface of the helper function.
In tests/plenary/org/autocompletion_spec.lua:
> + local files = helpers.create_agenda_files({ + 'a.org', + 'b/c.org', + }, { + '[[./ ', + '[[../ ', + }) ⬇️ Suggested change - local files = helpers.create_agenda_files({ - 'a.org', - 'b/c.org', - }, { - '[[./ ', - '[[../ ', - }) + local files = helpers.create_agenda_files({ + { + filename = 'a.org', + content = { {'[[./'}}, + }, + { + filename = 'b.org', + content = {} + } + })
More specific test case B.
In tests/plenary/org/autocompletion_spec.lua:
> + local files = helpers.create_agenda_files({ + 'a.org', + 'b/c.org', + }, { + '[[./ ', + '[[../ ', + }) ⬇️ Suggested change - local files = helpers.create_agenda_files({ - 'a.org', - 'b/c.org', - }, { - '[[./ ', - '[[../ ', - }) + local files = helpers.create_agenda_files({ + { + filename = 'a.org', + content = {}, + }, + { + filename = 'b.org', + content = { {'[[../'} } + }
More specific test case A.
In tests/plenary/org/autocompletion_spec.lua:
> @@ -339,6 +339,39 @@ describe('Autocompletion', function() { menu = '[Org]', word = 'Title without anchor' }, }, result) end) + + it('should work on relative paths', function() + local files = helpers.create_agenda_files({ + 'a.org', + 'b/c.org', + }, { + '[[./ ', + '[[../ ',
I also see now, that you contributed this function - I thought it already existed.
I have actually one last improvement: Can you change the interface of the function in that way, that it takes a list of tables, each one for each agenda file. And that each entry in this table is again an associative table with the keys filename and content. While filename is just a string, content would be again a table, each entry a line. This makes your function reusable for more complicated use cases with multiline content for an agenda file. I already have several test cases in mind, where this might be very useful.
In tests/plenary/org/autocompletion_spec.lua:
> @@ -339,6 +339,39 @@ describe('Autocompletion', function() { menu = '[Org]', word = 'Title without anchor' }, }, result) end) + + it('should work on relative paths', function() + local files = helpers.create_agenda_files({ + 'a.org', + 'b/c.org', + }, { + '[[./ ', + '[[../ ',
And sorry for the inconvenience, I use the review functions of Github actually the first time and just found the "Review in workspace" feature, which is actually great. Wished I found it earlier.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you authored the thread.Message ID: ***@***.***>
|
@kristijanhusak Can we merge this? I have tested it and use it daily (is merged on my personal development branch). Would be great to bring it to upstream. I have also a further extension in mind (emacs feature), which is depending on this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't test it yet, but I'd like few things to be addressed first.
@@ -116,7 +117,7 @@ function Url:get_file() | |||
if not self:is_file() then | |||
return nil | |||
end | |||
return self.path | |||
return self.realpath or self.path |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add realpath to annotations.
---@return table | ||
local function create_agenda_files(filenames, contents) | ||
-- NOTE: content is only 1 line for 1 file | ||
local temp_fname = vim.fn.tempname() | ||
local temp_dir = vim.fn.fnamemodify(temp_fname, ':p:h') | ||
-- clear temp dir | ||
vim.fn.delete(temp_dir .. '/*', 'rf') | ||
local files = {} | ||
local agenda_files = {} | ||
for i, filename in ipairs(filenames) do | ||
local fname = temp_dir .. '/' .. filename | ||
fname = vim.fn.fnamemodify(fname, ':p') | ||
if fname then | ||
local dir = vim.fn.fnamemodify(fname, ':p:h') | ||
vim.fn.mkdir(dir, 'p') | ||
vim.fn.writefile({ contents[i] }, fname) | ||
files[filename] = fname | ||
table.insert(agenda_files, fname) | ||
end | ||
end | ||
local cfg = vim.tbl_extend('force', { | ||
org_agenda_files = agenda_files, | ||
}, {}) | ||
local org = orgmode.setup(cfg) | ||
org:init() | ||
return files | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with @seflue on this. We can also add the 2nd parameter to be config, the same way we have it for create_agenda_file
.
@kristijanhusak I integrated the suggested changes on my local version of this branch. Should I just create a new PR to get these changes upstream? |
@seflue how far you on this? We can merge this and integrate the suggested changes as part of that PR if you have something ready. |
I just have the suggested changes ready, but didn't start on the new feature. I didn't start on it, knowing that the PR is still not merged. |
Ok, merging this in. You can prepare the PR with the fixes. |
…vim-orgmode#749) * feat(core): enhance org-insert-link, add completion for relative path or ~/ _squash: keep Url.path, and add a realpath filed fix: make sure realpath and path's ends are matched e.g. /path/to/me ../to/me /path/to/me/ ../to/me/ refactor: remove unused flag refactor: add comments on trailing slash _fix * test: add unit test for relative dirs --------- Co-authored-by: fanyunqian <fanyunqian@sensetime.com>
* fix: add realpath annotation * refactor: test helper --------- Co-authored-by: Sebastian Flügge <seflue@users.noreply.github.com>
Hi guys, I am trying to hack for ~/ prefixs.
Even if the cmp is configured with org-mode and path sources, the
<space>oli
cannot auto-complete the~/
prefix.Also, this issue is the same at emacs org-mode.
It is useful as I have multiple machines to sync with. I set my org folder as
~/org/
, but the~
can be/User/pf/
/home/pf/
Any suggestion is appreciated. :)