From 9934a8845b510276511e8efb357ccb22b4771838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Fl=C3=BCgge?= Date: Sun, 2 Jun 2024 09:33:19 +0200 Subject: [PATCH] feat: Allow to add more org file locations (#42) Supporting more then one org file locations allows the user to integrate existing orgmode agenda files into the org-roam knowledge graph. Implements #42. --- DOCS.org | 44 ++++++++++- README.org | 8 +- lua/org-roam.lua | 1 + lua/org-roam/config.lua | 10 +++ lua/org-roam/database.lua | 12 ++- lua/org-roam/setup/database.lua | 1 + spec/fixture/external/dir_1/one.org | 7 ++ spec/fixture/external/dir_1/test.txt | 0 spec/fixture/external/dir_2/two.org | 6 ++ spec/fixture/external/dir_3/five.org | 0 spec/fixture/external/dir_3/four.org | 0 spec/fixture/external/dir_3/three.org | 6 ++ .../roam/202406090101010101-Some_topic.org | 0 spec/fixture/roam/daily/2024-06-09.org | 0 spec/setup_spec.lua | 73 +++++++++++++++++++ 15 files changed, 163 insertions(+), 5 deletions(-) create mode 100644 spec/fixture/external/dir_1/one.org create mode 100644 spec/fixture/external/dir_1/test.txt create mode 100644 spec/fixture/external/dir_2/two.org create mode 100644 spec/fixture/external/dir_3/five.org create mode 100644 spec/fixture/external/dir_3/four.org create mode 100644 spec/fixture/external/dir_3/three.org create mode 100644 spec/fixture/roam/202406090101010101-Some_topic.org create mode 100644 spec/fixture/roam/daily/2024-06-09.org diff --git a/DOCS.org b/DOCS.org index a828c78..bdc634b 100644 --- a/DOCS.org +++ b/DOCS.org @@ -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. @@ -686,6 +725,7 @@ }) #+end_src + ** templates A map of templates associated with roam. These have the exact same format diff --git a/README.org b/README.org index 9b92e25..5b6c646 100644 --- a/README.org +++ b/README.org @@ -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 } diff --git a/lua/org-roam.lua b/lua/org-roam.lua index b713aa4..1019aa6 100644 --- a/lua/org-roam.lua +++ b/lua/org-roam.lua @@ -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 diff --git a/lua/org-roam/config.lua b/lua/org-roam/config.lua index 5cd78ad..c9c5e46 100644 --- a/lua/org-roam/config.lua +++ b/lua/org-roam/config.lua @@ -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 = { diff --git a/lua/org-roam/database.lua b/lua/org-roam/database.lua index 8cadaf5..6e20e94 100644 --- a/lua/org-roam/database.lua +++ b/lua/org-roam/database.lua @@ -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 = {} @@ -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 @@ -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 @@ -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 function M:internal() diff --git a/lua/org-roam/setup/database.lua b/lua/org-roam/setup/database.lua index 210b800..829de43 100644 --- a/lua/org-roam/setup/database.lua +++ b/lua/org-roam/setup/database.lua @@ -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 diff --git a/spec/fixture/external/dir_1/one.org b/spec/fixture/external/dir_1/one.org new file mode 100644 index 0000000..d3569b3 --- /dev/null +++ b/spec/fixture/external/dir_1/one.org @@ -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]] diff --git a/spec/fixture/external/dir_1/test.txt b/spec/fixture/external/dir_1/test.txt new file mode 100644 index 0000000..e69de29 diff --git a/spec/fixture/external/dir_2/two.org b/spec/fixture/external/dir_2/two.org new file mode 100644 index 0000000..2d309fe --- /dev/null +++ b/spec/fixture/external/dir_2/two.org @@ -0,0 +1,6 @@ +:PROPERTIES: +:ID: 33933a96-fb92-4979-976b-4f2f4048a978 +:END: +#+title: Two + +[[id:83de487d-3e29-48a4-8a0b-70663f977d5e][One]] diff --git a/spec/fixture/external/dir_3/five.org b/spec/fixture/external/dir_3/five.org new file mode 100644 index 0000000..e69de29 diff --git a/spec/fixture/external/dir_3/four.org b/spec/fixture/external/dir_3/four.org new file mode 100644 index 0000000..e69de29 diff --git a/spec/fixture/external/dir_3/three.org b/spec/fixture/external/dir_3/three.org new file mode 100644 index 0000000..9e66561 --- /dev/null +++ b/spec/fixture/external/dir_3/three.org @@ -0,0 +1,6 @@ +:PROPERTIES: +:ID: 41a787b7-81e0-49b1-be52-42c00270501c +:END: +#+title: Three + +[[id:83de487d-3e29-48a4-8a0b-70663f977d5e][One]] diff --git a/spec/fixture/roam/202406090101010101-Some_topic.org b/spec/fixture/roam/202406090101010101-Some_topic.org new file mode 100644 index 0000000..e69de29 diff --git a/spec/fixture/roam/daily/2024-06-09.org b/spec/fixture/roam/daily/2024-06-09.org new file mode 100644 index 0000000..e69de29 diff --git a/spec/setup_spec.lua b/spec/setup_spec.lua index bbe0123..641b064 100644 --- a/spec/setup_spec.lua +++ b/spec/setup_spec.lua @@ -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)