From 34a41e809c427d2d27724358ce40c3a413b99e34 Mon Sep 17 00:00:00 2001
From: Daniel Mathiot <d.danymat@gmail.com>
Date: Sat, 18 Sep 2021 13:24:03 +0200
Subject: [PATCH] feat: retrieve/generate links for files in the current
 workspace  (#2)

---
 .../core/integrations/telescope/module.lua    |  12 +-
 lua/telescope/_extensions/neorg.lua           |  10 +-
 .../_extensions/neorg/find_linkable.lua       |  19 ++-
 .../_extensions/neorg/insert_link.lua         | 146 ++++++++++++++----
 4 files changed, 142 insertions(+), 45 deletions(-)

diff --git a/lua/neorg/modules/core/integrations/telescope/module.lua b/lua/neorg/modules/core/integrations/telescope/module.lua
index c847aff..26a47e5 100644
--- a/lua/neorg/modules/core/integrations/telescope/module.lua
+++ b/lua/neorg/modules/core/integrations/telescope/module.lua
@@ -2,7 +2,7 @@
 	A Neorg module designed to integrate telescope.nvim
 --]]
 
-require('neorg.modules.base')
+require("neorg.modules.base")
 
 local module = neorg.modules.create("core.integrations.telescope")
 
@@ -11,18 +11,18 @@ module.setup = function()
 end
 
 module.load = function()
-	local telescope_loaded, telescope = pcall(require, 'telescope')
+	local telescope_loaded, telescope = pcall(require, "telescope")
 
 	assert(telescope_loaded, telescope)
 
-	telescope.load_extension('neorg')
+	telescope.load_extension("neorg")
 
 	module.required["core.keybinds"].register_keybinds(module.name, { "find_linkable", "insert_link" })
 end
 
 module.public = {
-	find_linkable = require('telescope._extensions.neorg.find_linkable'),
-	insert_link = require('telescope._extensions.neorg.insert_link')
+	find_linkable = require("telescope._extensions.neorg.find_linkable"),
+	insert_link = require("telescope._extensions.neorg.insert_link"),
 }
 
 module.on_event = function(event)
@@ -37,7 +37,7 @@ module.events.subscribed = {
 	["core.keybinds"] = {
 		["core.integrations.telescope.find_linkable"] = true,
 		["core.integrations.telescope.insert_link"] = true,
-	}
+	},
 }
 
 return module
diff --git a/lua/telescope/_extensions/neorg.lua b/lua/telescope/_extensions/neorg.lua
index c427aaf..82bac92 100644
--- a/lua/telescope/_extensions/neorg.lua
+++ b/lua/telescope/_extensions/neorg.lua
@@ -1,6 +1,6 @@
-return require('telescope').register_extension {
+return require("telescope").register_extension({
 	exports = {
-		find_linkable = require('neorg.modules.core.integrations.telescope.module').public.find_linkable,
-		insert_link = require('neorg.modules.core.integrations.telescope.module').public.insert_link,
-	}
-}
+		find_linkable = require("neorg.modules.core.integrations.telescope.module").public.find_linkable,
+		insert_link = require("neorg.modules.core.integrations.telescope.module").public.insert_link,
+	},
+})
diff --git a/lua/telescope/_extensions/neorg/find_linkable.lua b/lua/telescope/_extensions/neorg/find_linkable.lua
index 6b186d8..0e9033b 100644
--- a/lua/telescope/_extensions/neorg/find_linkable.lua
+++ b/lua/telescope/_extensions/neorg/find_linkable.lua
@@ -1,4 +1,4 @@
-local neorg_loaded, _ = pcall(require, 'neorg.modules')
+local neorg_loaded, _ = pcall(require, "neorg.modules")
 
 assert(neorg_loaded, "Neorg is not loaded - please make sure to load Neorg first")
 
@@ -15,15 +15,18 @@ local function get_current_workspace()
 end
 
 return function(opts)
-    opts = opts or {}
+	opts = opts or {}
 
 	local current_workspace = get_current_workspace()
 
-	if current_workspace then
-		require('telescope.builtin').grep_string({
-			search = "^\\s*(\\*+|\\|{1,2})\\s+",
-			use_regex = true,
-			search_dirs = { current_workspace }
-		})
+	if not current_workspace then
+		return
 	end
+
+	require("telescope.builtin").grep_string({
+		search = "^\\s*(\\*+|\\|{1,2})\\s+",
+		use_regex = true,
+		search_dirs = { current_workspace },
+		prompt_title = "Find in Norg files",
+	})
 end
diff --git a/lua/telescope/_extensions/neorg/insert_link.lua b/lua/telescope/_extensions/neorg/insert_link.lua
index 9790965..0796b98 100644
--- a/lua/telescope/_extensions/neorg/insert_link.lua
+++ b/lua/telescope/_extensions/neorg/insert_link.lua
@@ -1,47 +1,118 @@
-local actions = require('telescope.actions')
-local actions_set = require('telescope.actions.set')
-local finders = require('telescope.finders')
-local pickers = require('telescope.pickers')
-local conf = require('telescope.config').values
+local actions = require("telescope.actions")
+local actions_set = require("telescope.actions.set")
+local finders = require("telescope.finders")
+local pickers = require("telescope.pickers")
+local conf = require("telescope.config").values
 
-local neorg_loaded, _ = pcall(require, 'neorg.modules')
+local neorg_loaded, _ = pcall(require, "neorg.modules")
 
 assert(neorg_loaded, "Neorg is not loaded - please make sure to load Neorg first")
 
-local function get_linkables()
-	local ret = {}
+--- Get a list of all norg files in current workspace. Returns { workspace_path, norg_files }
+--- @return table
+local function get_norg_files()
+    local dirman = neorg.modules.get_module("core.norg.dirman")
 
-	local lines = vim.api.nvim_buf_get_lines(0, 0, -1, true)
+    if not dirman then
+        return nil
+    end
 
-	for i, line in ipairs(lines) do
-		local heading = { line:match("^%s*(%*+%s+(.+))$") }
-		if not vim.tbl_isempty(heading) then
-			table.insert(ret, { line = i, linkable = heading[2], display = heading[1] })
-		end
+    local current_workspace = dirman.get_current_workspace()
 
-		local marker_or_drawer = { line:match("^%s*(%|%|?%s+(.+))$") }
-		if not vim.tbl_isempty(marker_or_drawer) then
-			table.insert(ret, { line = i, linkable = marker_or_drawer[2], display = marker_or_drawer[1] })
-		end
-	end
+    local norg_files = dirman.get_norg_files(current_workspace[1])
 
-	return ret
+    return { current_workspace[2], norg_files }
+end
+
+--- Creates links for a `file` specified by `bufnr`
+--- @param bufnr number
+--- @param file string
+--- @return table
+local function get_linkables(bufnr, file)
+    local ret = {}
+
+    if file then
+        file = file:gsub(".norg", "")
+    end
+
+    local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, true)
+
+    for i, line in ipairs(lines) do
+        local heading = { line:match("^%s*(%*+%s+(.+))$") }
+        if not vim.tbl_isempty(heading) then
+            table.insert(ret, { line = i, linkable = heading[2], display = heading[1], file = file })
+        end
+
+        local marker_or_drawer = { line:match("^%s*(%|%|?%s+(.+))$") }
+        if not vim.tbl_isempty(marker_or_drawer) then
+            table.insert(ret, { line = i, linkable = marker_or_drawer[2], display = marker_or_drawer[1], file = file })
+        end
+    end
+
+    return ret
+end
+
+--- Generate links for telescope
+--- @return table
+local function generate_links()
+    local res = {}
+    local dirman = neorg.modules.get_module("core.norg.dirman")
+
+    if not dirman then
+        return nil
+    end
+
+    local files = get_norg_files()
+
+    if not files[2] then
+        return
+    end
+
+    for _, file in pairs(files[2]) do
+        local full_path_file = files[1] .. "/" .. file
+        local bufnr = dirman.get_file_bufnr(full_path_file)
+        if not bufnr then
+            return
+        end
+
+        vim.fn.bufload(full_path_file)
+
+        -- Because we do not want file name to appear in a link to the same file
+        local file_inserted = (function ()
+            if vim.api.nvim_get_current_buf() == bufnr then
+                return nil
+            else
+                return file
+            end
+        end)()
+
+        local links = get_linkables(bufnr, file_inserted)
+
+        if vim.api.nvim_get_current_buf() ~= bufnr then
+            vim.cmd('bunload! ' .. bufnr)
+        end
+
+        vim.list_extend(res, links)
+    end
+
+    return res
 end
 
 return function(opts)
     opts = opts or {}
 
-	pickers.new(opts, {
-		prompt_title = "Insert Link",
+    pickers.new(opts, {
+        prompt_title = "Insert Link",
         results_title = "Linkables",
         finder = finders.new_table({
-            results = get_linkables(),
+            results = generate_links(),
             entry_maker = function(entry)
                 return {
                     value = entry.line,
                     display = entry.display,
                     ordinal = entry.linkable,
                     lnum = entry.line,
+                    file = entry.file
                 }
             end,
         }),
@@ -51,11 +122,34 @@ return function(opts)
         attach_mappings = function(prompt_bufnr)
             actions_set.select:replace(function()
                 local entry = actions.get_selected_entry()
-				actions.close(prompt_bufnr)
-                vim.api.nvim_put({ "[" .. entry.ordinal:gsub(":$", "") .. "]" .. "(" .. entry.display:gsub("^(%W+)%s+.+", "%1") .. entry.ordinal:gsub("[%*#%|_]", "\\%1") .. ")" }, "c", false, true)
+                actions.close(prompt_bufnr)
+
+                local inserted_file = (function ()
+                    if entry.file then
+                        return ":" .. entry.file .. ":"
+                    else
+                        return ""
+                    end
+                end)()
+
+                vim.api.nvim_put(
+                    {
+                        "["
+                            .. entry.ordinal:gsub(":$", "")
+                            .. "]"
+                            .. "("
+                            .. inserted_file
+                            .. entry.display:gsub("^(%W+)%s+.+", "%1")
+                            .. entry.ordinal:gsub("[%*#%|_]", "\\%1")
+                            .. ")",
+                    },
+                    "c",
+                    false,
+                    true
+                )
                 vim.api.nvim_feedkeys("f)a", "t", false)
             end)
             return true
         end,
-	}):find()
+    }):find()
 end