Skip to content

Commit

Permalink
feat(attach): add config org_attach_dir_relative
Browse files Browse the repository at this point in the history
This reverts commit 272da8c217455f2fde59411f59e5e51ea44a3125.
  • Loading branch information
troiganto committed Feb 9, 2025
1 parent 492125b commit 73a070b
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 7 deletions.
15 changes: 13 additions & 2 deletions docs/configuration.org
Original file line number Diff line number Diff line change
Expand Up @@ -1168,6 +1168,16 @@ be inherited.
The directory where attachments are stored. If this is a relative path, it
will be interpreted relative to the directory where the Org file lives.

*** org_attach_dir_relative
:PROPERTIES:
:CUSTOM_ID: org_attach_dir_relative
:END:
- Type: =boolean=
- Default: =false=

If =true=, whenever you add a =DIR= property to a headline, it is added as
a relative path. The default is to only add absolute paths.

*** org_attach_auto_tag
:PROPERTIES:
:CUSTOM_ID: org_attach_auto_tag
Expand Down Expand Up @@ -2996,8 +3006,9 @@ file).
Attaching a file puts it in a directory associated with the attachment node.
Based on [[#org_attach_preferred_new_method][org_attach_preferred_new_method]], this either uses the =ID= or
the =DIR= property. See also [[#org_attach_id_dir][org_attach_id_dir]],
[[#org_attach_id_to_path_function_list][org_attach_id_to_path_function_list]] and [[#org_attach_use_inheritance][org_attach_use_inheritance]] on how
to further customize the attachments directory.
[[#org_attach_dir_relative][org_attach_dir_relative]], [[#org_attach_id_to_path_function_list][org_attach_id_to_path_function_list]] and
[[#org_attach_use_inheritance][org_attach_use_inheritance]] on how to further customize the attachments
directory.

Attachment links are supported. A link like =[[attachment:file.txt]]=
looks up =file.txt= in the current node's attachments directory and opens
Expand Down
3 changes: 2 additions & 1 deletion lua/orgmode/attach/core.lua
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,8 @@ end
---Set the DIR node property and ask to move files there.
---
---The property defines the directory that is used for attachments
---of the entry.
---of the entry. Creates relative links if `org_attach_dir_relative'
---is true.
---
---@param node OrgAttachNode
---@param new_dir string
Expand Down
3 changes: 2 additions & 1 deletion lua/orgmode/attach/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,8 @@ end
---Set the DIR node property and ask to move files there.
---
---The property defines the directory that is used for attachments
---of the entry.
---of the entry. Creates relative links if `org_attach_dir_relative'
---is true.
---
---@param node? OrgAttachNode
---@return string | nil new_dir
Expand Down
10 changes: 7 additions & 3 deletions lua/orgmode/attach/node.lua
Original file line number Diff line number Diff line change
Expand Up @@ -178,15 +178,19 @@ end

---Set the attachment directory on the current node.
---
---In addition to `set_property()`, this also ensures that the path is always
---absolute.
---In addition to `set_property()`, this also adjusts the path to be relative,
---if required by `org_attach_dir_relative`.
---
---@param dir string
---@return string new_dir absolute attachment directory
---@overload fun(): nil
function AttachNode:set_dir(dir)
if dir then
dir = vim.fn.fnamemodify(dir, ':p')
if config.org_attach_dir_relative then
dir = fs_utils.make_relative(dir, vim.fs.dirname(self.file.filename))
else
dir = vim.fn.fnamemodify(dir, ':p')
end
end
self:set_property('DIR', dir)
return dir and self:_make_absolute(dir)
Expand Down
1 change: 1 addition & 0 deletions lua/orgmode/config/defaults.lua
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ local DefaultConfig = {
[':noweb'] = 'no',
},
org_attach_id_dir = './data/',
org_attach_dir_relative = false,
org_attach_auto_tag = 'ATTACH',
org_attach_preferred_new_method = 'id',
org_attach_method = 'cp',
Expand Down
33 changes: 33 additions & 0 deletions lua/orgmode/utils/fs.lua
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,37 @@ function M.trim_common_root(paths)
return result
end

---@param filepath string an absolute path
---@param base string an absolute path to an ancestor of filepath;
--- here, `'.'` represents the current working directory, and
--- *not* the current file's directory.
---@return string filepath_relative_to_base
function M.make_relative(filepath, base)
vim.validate({
filepath = { filepath, 'string', false },
base = { base, 'string', false },
})
filepath = vim.fn.fnamemodify(filepath, ':p')
base = vim.fn.fnamemodify(base, ':p')
if base:sub(-1) ~= '/' then
base = base .. '/'
end
local levels_up = 0
for parent in vim.fs.parents(base) do
if parent:sub(-1) ~= '/' then
parent = parent .. '/'
end
if vim.startswith(filepath, parent) then
filepath = filepath:sub(parent:len() + 1)
if levels_up > 0 then
return vim.fs.joinpath(string.rep('..', levels_up, '/'), filepath)
end
return vim.fs.joinpath('.', filepath)
end
levels_up = levels_up + 1
end
-- No common root, just return the absolute path.
return filepath
end

return M
48 changes: 48 additions & 0 deletions tests/plenary/utils/fs_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,51 @@ describe('get_real_path', function()
assert.is.False(fs_utils.get_real_path('.'))
end)
end)

describe('make_relative', function()
local path = fs_utils.get_real_path(file.filename) ---@cast path string
local basename = vim.fs.basename(path)
local dirname = vim.fs.dirname(path)
local dirname_slash = vim.fs.joinpath(dirname, '')
local root = path
for parent in vim.fs.parents(path) do
root = parent
end

it('gets the basename', function()
local expected = vim.fs.joinpath('.', basename)
local actual = fs_utils.make_relative(path, dirname)
assert.are.same(expected, actual)
end)

it('gets the basename with trailing slash', function()
local expected = vim.fs.joinpath('.', basename)
local actual = fs_utils.make_relative(path, dirname_slash)
assert.are.same(expected, actual)
end)

it('works one level up', function()
local parent_name = vim.fs.basename(dirname)
local expected = vim.fs.joinpath('.', parent_name, basename)
local actual = fs_utils.make_relative(path, vim.fs.dirname(dirname))
assert.are.same(expected, actual)
end)

it('works one level up with trailing slash', function()
local parent_name = vim.fs.basename(dirname)
local expected = vim.fs.joinpath('.', parent_name, basename)
local actual = fs_utils.make_relative(path, vim.fs.dirname(dirname) .. '/')
assert.are.same(expected, actual)
end)

it('produces a relative path even at the root', function()
local relpath = fs_utils.make_relative(path, root)
assert(vim.endswith(path, relpath))
end)

it('climbs up via ..', function()
local relpath = fs_utils.make_relative(root, path)
local only_cdup = vim.regex('\\V\\(../\\)\\+')
assert(only_cdup:match_str(relpath))
end)
end)

0 comments on commit 73a070b

Please sign in to comment.