I currently have this (working) configuration in my neovim:
{
"nvim-telescope/telescope.nvim",
dependencies = {
...
"jvgrootveld/telescope-zoxide",
},
config = function()
-- First setup telescope
local telescope = require("telescope")
local builtin = require("telescope.builtin")
telescope.setup({
...
extensions = {
zoxide = {
mappings = {
default = {
keepinsert = true,
action = function(selection)
builtin.find_files({ cwd = selection.path }) -- the line in question
end,
},
},
},
},
})
telescope.load_extension("zoxide")
end,
...
},
If I change the line in question to
telescope.builtin.find_files({ cwd = selection.path })
I get the following error:
E5108: Error executing lua: /home/sbeer/.config/nvim/lua/plugins/telescope.lua:38: attempt to index field 'builtin' (a nil value)
stack traceback:
/home/sbeer/.config/nvim/lua/plugins/telescope.lua:38: in function 'action'
...lescope-zoxide/lua/telescope/_extensions/zoxide/list.lua:86: in function 'run_replace_or_original'
...re/nvim/lazy/telescope.nvim/lua/telescope/actions/mt.lua:65: in function 'key_func'
...hare/nvim/lazy/telescope.nvim/lua/telescope/mappings.lua:253: in function <...hare/nvim/lazy/telescope.nvim/lua/telescope/mappings.lua:252>
What exactly is the difference between the two?
As pointed out in this answer,
It is up to the designer of the module to decide what can be seen from the outside.
The working require("telescope.builtin")
approach loads a separate module that contains the find_files
function. However, that module, and so its function, apparently is not automatically part of the telescope
table/module.
Since the builtin
module is not accessible from the outside by default, Lua in this instance assumes that builtin
in the reference telescope.builtin
is a field of the telescope module, which it isn't, resulting in the error "attempt to index **field** 'builtin' (a nil value)."
Now, if you really want to use the require("some").module
approach, you may add a line to expose builtin
as a field of telescope
explicitly, like so:
local telescope = require("telescope")
telescope.builtin = require("telescope.builtin") -- Add this line
Then the line in question would work correctly:
telescope.builtin.find_files({ cwd = selection.path })
But to avoid ambiguity and unnecessary additions to the telescope
namespace, I'd say it’s better to stick with the working version:
local builtin = require("telescope.builtin")
...
builtin.find_files({ cwd = selection.path })
Finally, I think it was a deliberate intention by the developers of the telescope module to have that structure, as their own code snippets show the require("some.module")
approach:
--- To use any of Telescope's default options or any picker-specific options, call your desired picker by passing a lua
--- table to the picker with all of the options you want to use. Here's an example with the live_grep picker:
---
--- <code>
--- :lua require('telescope.builtin').live_grep({
--- prompt_title = 'find string in open buffers...',
--- grep_open_files = true
--- })
--- -- or with dropdown theme
--- :lua require('telescope.builtin').find_files(require('telescope.themes').get_dropdown{
--- previewer = false
--- })
--- </code>
You can check such things by iterating over the module's fields (as it typically has the format of a simple table):
local telescope = require("telescope")
for key, value in pairs(telescope) do
print(key, value)
end
This will list all keys (field names) and their corresponding values in the module.