Skip to content

Instantly share code, notes, and snippets.

@iagoleal
Created September 10, 2021 20:11
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save iagoleal/92bd781dae1926525cd5e049eb32d64b to your computer and use it in GitHub Desktop.
Save iagoleal/92bd781dae1926525cd5e049eb32d64b to your computer and use it in GitHub Desktop.
Properly open lua and fennel required files via gf
local fmt = string.format
-- Iterator that splits a string o a given delimiter
local function split(str, delim)
delim = delim or "%s"
return string.gmatch(str, fmt('[^%s]+', delim))
end
-- Find the proper directory separator depending
-- on lua installation or OS.
local function dir_separator()
-- Look at package.config for directory separator string (it's the first line)
if package.config then
return string.match(package.config, '^[^\n]')
elseif vim.fn.has('win32') == 1 then
return '\\'
else
return '/'
end
end
-- Search for lua traditional include paths.
-- This mimics how require internally works.
local function include_paths(fname, ext)
ext = ext or "lua"
local sep = dir_separator()
local paths = string.gsub(package.path, '%?', fname)
for path in split(paths, "%;") do
if vim.fn.filereadable(path) == 1 then
return path
end
end
end
-- Search for nvim lua include paths
local function include_rtpaths(fname, ext)
ext = ext or "lua"
local sep = dir_separator()
local rtpaths = vim.api.nvim_list_runtime_paths()
local modfile, initfile = fmt('%s.%s', fname, ext), fmt('init.%s', ext)
for _, path in ipairs(rtpaths) do
-- Look on runtime path for 'lua/*.lua' files
local path1 = table.concat({path, ext, modfile}, sep)
if vim.fn.filereadable(path1) == 1 then
return path1
end
-- Look on runtime path for 'lua/*/init.lua' files
local path2 = table.concat({path, ext, fname, initfile}, sep)
if vim.fn.filereadable(path2) == 1 then
return path2
end
end
end
-- Global function that searches the path for the required file
function find_required_path(module)
-- Look at package.config for directory separator string (it's the first line)
local sep = string.match(package.config, '^[^\n]')
-- Properly change '.' to separator (probably '/' on *nix and '\' on Windows)
local fname = vim.fn.substitute(module, "\\.", sep, "g")
local f
---- First search for lua modules
f = include_paths(fname, 'lua')
if f then return f end
-- This part is just for nvim modules
f = include_rtpaths(fname, 'lua')
if f then return f end
---- Now search for Fennel modules
f = include_paths(fname, 'fnl')
if f then return f end
-- This part is just for nvim modules
f = include_rtpaths(fname, 'fnl')
if f then return f end
end
-- Set options to open require with gf
vim.opt_local.include = [=[\v<((do|load)file|require)\s*\(?['"]\zs[^'"]+\ze['"]]=]
vim.opt_local.includeexpr = "v:lua.find_required_path(v:fname)"
@iagoleal
Copy link
Author

Adapted from the vimscript in this link to also support Windows and Fennel files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment