diff --git a/lua/orgmode/api/file.lua b/lua/orgmode/api/file.lua index 349a743c1..87b2695d1 100644 --- a/lua/orgmode/api/file.lua +++ b/lua/orgmode/api/file.lua @@ -1,5 +1,7 @@ ---@diagnostic disable: invisible local OrgHeadline = require('orgmode.api.headline') +local Hyperlinks = require('orgmode.org.hyperlinks') +local org = require('orgmode') ---@class OrgApiFile ---@field category string current file category name. By default it's only filename without extension unless defined differently via #+CATEGORY directive @@ -92,4 +94,30 @@ function OrgFile:get_closest_headline(cursor) return nil end +--- Get a link destination as string +--- +--- Depending if org_id_link_to_org_use_id is set the format is +--- +--- id:::*title and the id is created if not existing +--- or +--- file:::*title +--- +--- The result is meant to be used as link_location for OrgApi.insert_link. +--- @return string +function OrgFile:get_link() + local filename = self.filename + local bufnr = vim.fn.bufnr(filename) + + if bufnr == -1 or not vim.api.nvim_buf_is_loaded(bufnr) then + -- do remote edit + return org.files + :update_file(filename, function(file) + return Hyperlinks.get_link_to_file(file) + end) + :wait() + end + + return Hyperlinks.get_link_to_file(self._file) +end + return OrgFile diff --git a/lua/orgmode/api/headline.lua b/lua/orgmode/api/headline.lua index 88d7c6a3e..282d05fe7 100644 --- a/lua/orgmode/api/headline.lua +++ b/lua/orgmode/api/headline.lua @@ -3,6 +3,7 @@ local PriorityState = require('orgmode.objects.priority_state') local Date = require('orgmode.objects.date') local Calendar = require('orgmode.objects.calendar') local Promise = require('orgmode.utils.promise') +local Hyperlinks = require('orgmode.org.hyperlinks') local org = require('orgmode') ---@class OrgApiHeadline @@ -259,4 +260,30 @@ function OrgHeadline:_do_action(action) end) end +--- Get a link destination as string +--- +--- Depending if org_id_link_to_org_use_id is set the format is +--- +--- id:::*title and the id is created if not existing +--- or +--- file:::*title +--- +--- The result is meant to be used as link_location for OrgApi.insert_link. +--- @return string +function OrgHeadline:get_link() + local filename = self.file.filename + local bufnr = vim.fn.bufnr(filename) + + if bufnr == -1 or not vim.api.nvim_buf_is_loaded(bufnr) then + -- do remote edit + return org.files + :update_file(filename, function(_) + return Hyperlinks.get_link_to_headline(self._section) + end) + :wait() + end + + return Hyperlinks.get_link_to_headline(self._section) +end + return OrgHeadline diff --git a/lua/orgmode/api/init.lua b/lua/orgmode/api/init.lua index ad479e0b4..cf7926da5 100644 --- a/lua/orgmode/api/init.lua +++ b/lua/orgmode/api/init.lua @@ -2,7 +2,6 @@ local OrgFile = require('orgmode.api.file') local OrgHeadline = require('orgmode.api.headline') local Hyperlinks = require('orgmode.org.hyperlinks') -local Link = require('orgmode.org.hyperlinks.link') local orgmode = require('orgmode') ---@class OrgApiRefileOpts @@ -102,6 +101,12 @@ function OrgApi.refile(opts) end --- Insert a link to a given location at the current cursor position +--- +--- The expected format is +--- ::: +--- +--- If is *, is used as prefilled description for the link. +--- If is id, this format can also be used to pass a prefilled description. --- @param link_location string --- @return boolean function OrgApi.insert_link(link_location) diff --git a/lua/orgmode/files/file.lua b/lua/orgmode/files/file.lua index 8434afe91..736dc2f91 100644 --- a/lua/orgmode/files/file.lua +++ b/lua/orgmode/files/file.lua @@ -643,6 +643,7 @@ end memoize('get_category') --- Get the category name for this file +--- If no category is set, the filename without extension is returned --- @return string function OrgFile:get_category() local category = self:_get_directive('category') @@ -653,6 +654,19 @@ function OrgFile:get_category() return vim.fn.fnamemodify(self.filename, ':t:r') or '' end +memoize('get_title') +--- Get the title for this file +--- If no title is set, the filename without extension is returned +--- @return string +function OrgFile:get_title() + local title = self:_get_directive('title') + if title then + return title + end + + return vim.fn.fnamemodify(self.filename, ':t:r') or '' +end + memoize('get_opened_unfinished_headlines') ---@return OrgHeadline[] function OrgFile:get_opened_unfinished_headlines() @@ -703,6 +717,18 @@ function OrgFile:get_directive(directive_name) return self:_get_directive(directive_name) end +--- Get headline id or create a new one if it doesn't exist +--- @return string +function OrgFile:id_get_or_create() + local id = self:get_property('id') + if id then + return id + end + local org_id = require('orgmode.org.id').new() + self:set_property('ID', org_id) + return org_id +end + ---@private ---@return string | nil function OrgFile:_get_directive(directive_name) diff --git a/lua/orgmode/org/hyperlinks/init.lua b/lua/orgmode/org/hyperlinks/init.lua index 2dc6a5d7a..6f517f577 100644 --- a/lua/orgmode/org/hyperlinks/init.lua +++ b/lua/orgmode/org/hyperlinks/init.lua @@ -174,16 +174,32 @@ end ---@param headline OrgHeadline ---@param path? string function Hyperlinks.get_link_to_headline(headline, path) - path = path or utils.current_file_path() local title = headline:get_title() - local id + if config.org_id_link_to_org_use_id then - id = headline:id_get_or_create() + local id = headline:id_get_or_create() + if id then + return ('id:%s::*%s'):format(id, title) + end end - if config.org_id_link_to_org_use_id and id then - return ('id:%s::*%s'):format(id, title) + path = path or utils.current_file_path() + return ('file:%s::*%s'):format(path, title) +end + +---@param file OrgFile +---@param path? string +function Hyperlinks.get_link_to_file(file, path) + local title = file:get_title() + + if config.org_id_link_to_org_use_id then + local id = file:id_get_or_create() + if id then + return ('id:%s::*%s'):format(id, title) + end end + + path = path or file.filename return ('file:%s::*%s'):format(path, title) end