Skip to content

Commit

Permalink
feat: Allow to add more org file locations (#42)
Browse files Browse the repository at this point in the history
Supporting more then one org file locations allows the user to integrate
existing orgmode agenda files into the org-roam knowledge graph.

Implements #42.
  • Loading branch information
seflue committed Jun 22, 2024
1 parent 5943188 commit 9934a88
Show file tree
Hide file tree
Showing 15 changed files with 163 additions and 5 deletions.
44 changes: 42 additions & 2 deletions DOCS.org
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,56 @@

** directory

Path to the directory containing org files for use with org-roam.
Path to the directory containing org files for use with org-roam and where
org-roam stores org files which represent new nodes created with org-roam.

Takes a string representing the path to the directory, which can
can contain =~= that will expand to your home directory.

#+begin_src lua
require("org-roam").setup({
directory = "~/orgfiles",
directory = "~/orgroamfiles",
})
#+end_src

Configuring additional folders and files to be loaded by org-roam is also
supported, see [[#configuration-org_files][org_files]]:

** org_files

To include existing org files in the knowledge graph of org roam, additional
files can be registered. Supported syntax is like =org_agenda_files= in
orgmode. If the entry does not end on =.org= a directory is assumed and
searched recursively for org files.

#+begin_src lua
require("org-roam").setup({
org_files = {
"~/more_org_files",
"~/additional/org_files/*.org",
},
})
#+end_src

To actually connect the content of these files with org-roams knowledge
graph, you can use the "store link" feature of orgmode (=,ols=), which adds
an ID to an existing headline. This headline is then treated as a roam node
by org-roam.

If you want a whole file to be treated as a node by org-roam, you need to add
a global property section and a title at the top of the org file.

#+begin_example org
:PROPERTIES:
:ID: 8b2c3d3e-9800-4186-80e5-d07ce7bc5327
:END:
#+TITLE: My node
#+end_example

Tip: Because "store link" in orgmode currently does not support whole files, the
quick workaround is to apply =,ols= on a headline and move the =:PROPERTIES:=
section with the generated ID to the top of the file.

** bindings

Configuration settings used to specify keybindings.
Expand Down Expand Up @@ -686,6 +725,7 @@
})
#+end_src


** templates

A map of templates associated with roam. These have the exact same format
Expand Down
8 changes: 7 additions & 1 deletion README.org
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,13 @@ Requires *neovim 0.9.2+*.
},
config = function()
require("org-roam").setup({
directory = "~/orgfiles",
directory = "~/org_roam_files",
-- optional
org_files = {
"~/another_org_dir",
"~/some/folder/*.org",
"~/a/single/org_file.org",
}
})
end
}
Expand Down
1 change: 1 addition & 0 deletions lua/org-roam.lua
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ function M:new(config)
return Database:new({
db_path = instance.config.database.path,
directory = instance.config.directory,
org_files = instance.config.org_files,
})
end

Expand Down
10 changes: 10 additions & 0 deletions lua/org-roam/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,16 @@ local DEFAULT_CONFIG = {
},
},

---Additional org files to load. If an entry does not end on ".org" it assumes a directory and searches for org
---files recusrively.
---Supports globbing like org_agenda_files setting in orgmode
---@type string[]
org_files = {
-- ~/additonal_org_files,
-- ~/a/single/org_file.org,
-- ~/more/org/files/but/not/recusive/search/*.org
},

---Settings tied to org-roam immediate mode.
---@class org-roam.config.Immediate
immediate = {
Expand Down
12 changes: 10 additions & 2 deletions lua/org-roam/database.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ local schema = require("org-roam.database.schema")
---@field private __loader org-roam.database.Loader
---@field private __database_path string
---@field private __directory string
---@field private __org_files string[]
local M = {}

---Creates a new, unloaded instance of the database.
---@param opts {db_path:string, directory:string}
---@param opts {db_path:string, directory:string, org_files:string[]}
---@return org-roam.Database
function M:new(opts)
local instance = {}
Expand All @@ -28,6 +29,7 @@ function M:new(opts)
instance.__loader = nil
instance.__database_path = opts.db_path
instance.__directory = opts.directory
instance.__org_files = opts.org_files
return instance
end

Expand Down Expand Up @@ -73,9 +75,11 @@ end
function M:__get_loader()
local loader = self.__loader
if not loader then
local files = self.__org_files
table.insert(files, self.__directory)
loader = Loader:new({
database = self.__database_path,
files = self.__directory,
files = files,
})
self.__loader = loader
end
Expand All @@ -94,6 +98,10 @@ function M:files_path()
return self.__directory
end

function M:org_files()
return self.__org_files
end

---Returns the internal database wrapped by this interface.
---@return OrgPromise<org-roam.core.Database>
function M:internal()
Expand Down
1 change: 1 addition & 0 deletions lua/org-roam/setup/database.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ return function(roam)
roam.database = roam.database:new({
db_path = roam.config.database.path,
directory = roam.config.directory,
org_files = roam.config.org_files,
})

-- Load the database asynchronously, forcing a full sweep of directory
Expand Down
7 changes: 7 additions & 0 deletions spec/fixture/external/dir_1/one.org
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
:PROPERTIES:
:ID: 83de487d-3e29-48a4-8a0b-70663f977d5e
:END:
#+TITLE: one

[[id:33933a96-fb92-4979-976b-4f2f4048a978][Two]]
[[id:41a787b7-81e0-49b1-be52-42c00270501c][Three]]
Empty file.
6 changes: 6 additions & 0 deletions spec/fixture/external/dir_2/two.org
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
:PROPERTIES:
:ID: 33933a96-fb92-4979-976b-4f2f4048a978
:END:
#+title: Two

[[id:83de487d-3e29-48a4-8a0b-70663f977d5e][One]]
Empty file.
Empty file.
6 changes: 6 additions & 0 deletions spec/fixture/external/dir_3/three.org
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
:PROPERTIES:
:ID: 41a787b7-81e0-49b1-be52-42c00270501c
:END:
#+title: Three

[[id:83de487d-3e29-48a4-8a0b-70663f977d5e][One]]
Empty file.
Empty file.
73 changes: 73 additions & 0 deletions spec/setup_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,77 @@ describe("org-roam.setup", function()
assert.are.equal(db_path, roam.database:path())
assert.are.equal(directory, roam.database:files_path())
end)

local has_file_like = function(state, arguments)
local file_paths = arguments[1]
local patterns = arguments[2]
for _, pattern in ipairs(patterns) do
pattern = string.gsub(pattern, "-", "%%-") .. "$"
local match_found = false
for _, file_path in ipairs(file_paths) do
if file_path:match(pattern) then
match_found = true
break
end
end
if not match_found then
print(pattern .. "not found")
return false
end
end
return true
end

local say = require("say")
say:set_namespace("en")
say:set("assertion.has_property.positive", "Expected %s to match all file patterns of %s.")
say:set("assertion.has_property.negative", "Expected %s to not match all file patterns %s.")
assert:register(
"assertion",
"has_file_like",
has_file_like,
"assertion.has_property.positive",
"assertion.has_property.negative"
)

it("should load files", function()
local db_path = vim.fn.tempname() .. "-test-db"
local fixture_path = vim.fn.getcwd() .. "/spec/fixture/"
local directory = fixture_path .. "roam/"

local roam = utils.init_plugin({ setup = false })
roam.setup({
database = { path = db_path },
directory = directory,
org_files = {
fixture_path .. "/external/dir_1/*.org",
fixture_path .. "/external/dir_2/two.org",
fixture_path .. "/external/dir_3/",
},
}):wait()

local file_names = {
"Some_topic.org",
"2024-06-09.org",
"one.org",
"two.org",
"three.org",
"four.org",
"five.org",
}

local file_paths = {}
roam.database
:files({ force = true })
:next(function(opts)
for file_path, file in pairs(opts.all_files) do
table.insert(file_paths, file_path)
assert.is_not_nil(file)
end
end)
:wait()

---@diagnostic disable-next-line: undefined-field
assert.has.file.like(file_paths, file_names)
end)
end)

0 comments on commit 9934a88

Please sign in to comment.