Implement :BuildDir and :Build commands in Lua
Ported over from and improved for best integration with Neovim ecosystem https://code.infektor.net/config/vim/src/branch/master/autoload/build.vim
This commit is contained in:
parent
573c548245
commit
0656de97fa
1
after/ftplugin/c.lua
Normal file
1
after/ftplugin/c.lua
Normal file
@ -0,0 +1 @@
|
|||||||
|
require('build').create_commands()
|
@ -1 +1,3 @@
|
|||||||
vim.bo.commentstring = '//%s'
|
vim.bo.commentstring = '//%s'
|
||||||
|
|
||||||
|
require('build').create_commands()
|
||||||
|
1
init.lua
1
init.lua
@ -2,6 +2,7 @@ require('settings')
|
|||||||
require('mappings')
|
require('mappings')
|
||||||
require('netrw')
|
require('netrw')
|
||||||
require('autocmds')
|
require('autocmds')
|
||||||
|
require('build')
|
||||||
|
|
||||||
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
|
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
|
||||||
if not vim.loop.fs_stat(lazypath) then
|
if not vim.loop.fs_stat(lazypath) then
|
||||||
|
161
lua/build.lua
Normal file
161
lua/build.lua
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
local build = {}
|
||||||
|
|
||||||
|
build.dir = nil
|
||||||
|
|
||||||
|
local function echo(message, highlight)
|
||||||
|
vim.api.nvim_echo({ { message, highlight }, }, true, {})
|
||||||
|
end
|
||||||
|
|
||||||
|
function build.set_dir(dirname)
|
||||||
|
if not dirname then
|
||||||
|
build.select_dir()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local current_dir = vim.fn.getcwd()
|
||||||
|
local build_dir = current_dir .. '/' .. dirname
|
||||||
|
-- print(build_dir)
|
||||||
|
|
||||||
|
if vim.fn.isdirectory(build_dir) == 0 then
|
||||||
|
echo('directory does not exist: ' .. build_dir, 'Error')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if vim.fn.filereadable(build_dir .. '/compile_commands.json') == 0 then
|
||||||
|
echo('compile_commands.json not found in: ' .. build_dir, 'Error')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
build.dir = build_dir
|
||||||
|
|
||||||
|
-- Invoke async function to avoid blocking the UI
|
||||||
|
vim.schedule(function()
|
||||||
|
echo('Processing compile_commands.json with compdb ...', 'DiagnosticInfo')
|
||||||
|
|
||||||
|
-- Post-process compile_commands.json with compdb
|
||||||
|
local compile_commands = current_dir .. '/compile_commands.json'
|
||||||
|
local output = vim.fn.systemlist(
|
||||||
|
'compdb -p ' .. build.dir .. ' list > ' .. compile_commands)
|
||||||
|
if table.maxn(output) > 0 then
|
||||||
|
echo(vim.fn.join(output, '\n'), 'Error')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO: Configure cmake language server?
|
||||||
|
|
||||||
|
-- Restart clangd language server
|
||||||
|
vim.cmd [[ LspRestart clangd ]]
|
||||||
|
|
||||||
|
echo('Build directory selected: ' .. dirname, 'DiagnosticInfo')
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function build.select_dir(callback)
|
||||||
|
local dirs = build.list_dirs()
|
||||||
|
callback = callback or nil
|
||||||
|
|
||||||
|
if table.maxn(dirs) == 1 then
|
||||||
|
build.set_dir(dirs[1])
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if vim.fn.exists(':Telescope') > 0 then
|
||||||
|
-- Create a Telescope picker with custom action.
|
||||||
|
require('telescope.pickers').new({}, {
|
||||||
|
prompt_title = 'Select build directory',
|
||||||
|
finder = require('telescope.finders').new_table({ results = dirs }),
|
||||||
|
sorter = require("telescope.config").values.generic_sorter({}),
|
||||||
|
attach_mappings = function(bufnr, map)
|
||||||
|
-- Override the default confirm action
|
||||||
|
map('i', '<CR>', function()
|
||||||
|
-- Get the select build directory
|
||||||
|
local state = require('telescope.actions.state')
|
||||||
|
build.set_dir(state.get_selected_entry().value)
|
||||||
|
-- Close the Telescope floating window
|
||||||
|
require('telescope.actions').close(bufnr)
|
||||||
|
-- Invoke the callback if provided
|
||||||
|
if callback then callback() end
|
||||||
|
end)
|
||||||
|
return true
|
||||||
|
end,
|
||||||
|
layout_config = {
|
||||||
|
height = function(_, _, max_lines)
|
||||||
|
-- Limit the height based on the number of dirs
|
||||||
|
return math.min(max_lines, table.maxn(dirs) + 5)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
}):find()
|
||||||
|
else
|
||||||
|
-- Prompt user to choose dir with to inputlist
|
||||||
|
local choices = {}
|
||||||
|
for index, choice in ipairs(dirs) do
|
||||||
|
table.insert(choices, tostring(index) .. ': ' .. choice)
|
||||||
|
end
|
||||||
|
local index = vim.fn.inputlist(choices)
|
||||||
|
build.dir = dirs[index]
|
||||||
|
if callback then
|
||||||
|
callback()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function build.run(args)
|
||||||
|
-- Check if build dir set, if not prompt user to select one
|
||||||
|
if not build.dir then
|
||||||
|
build.select_dir(function() build.run(args) end)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local command = nil
|
||||||
|
if vim.fn.filereadable(build.dir .. '/build.ninja') then
|
||||||
|
command = 'ninja'
|
||||||
|
elseif vim.fn.filereadable(build.dir .. '/Makefile') then
|
||||||
|
command = 'make'
|
||||||
|
else
|
||||||
|
echo('could not find build.ninja or Makefile in: ' .. build.dir)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
command = command .. ' -C ' .. build.dir .. ' ' .. vim.fn.join(args, ' ')
|
||||||
|
-- TODO: Figure out how to make the terminal window close on success
|
||||||
|
-- TODO: Running the terminal in a togglable floating window might be nice
|
||||||
|
vim.fn.execute('split | terminal ' .. command)
|
||||||
|
end
|
||||||
|
|
||||||
|
function build.list_dirs()
|
||||||
|
local dirs = vim.fn.globpath('.', 'build*')
|
||||||
|
dirs = vim.fn.substitute(dirs, '\\.\\/', '', 'g')
|
||||||
|
return vim.fn.split(dirs)
|
||||||
|
end
|
||||||
|
|
||||||
|
function build.list_targets()
|
||||||
|
local targets = {}
|
||||||
|
if not build.dir then
|
||||||
|
return targets
|
||||||
|
end
|
||||||
|
if vim.fn.filereadable(build.dir .. '/build.ninja') then
|
||||||
|
-- Query ninja for the list of targets
|
||||||
|
targets = vim.fn.systemlist('ninja -C ' .. build.dir .. ' -t targets')
|
||||||
|
for index, target in ipairs(targets) do
|
||||||
|
targets[index] = string.sub(target, 1, string.find(target, ':') - 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- TODO: Support make, it's much less straight forwards than ninja.
|
||||||
|
return targets
|
||||||
|
end
|
||||||
|
|
||||||
|
function build.create_commands()
|
||||||
|
local buffer = vim.api.nvim_get_current_buf()
|
||||||
|
|
||||||
|
-- Create :BuildDir command
|
||||||
|
vim.api.nvim_buf_create_user_command(buffer, 'BuildDir', function(opts)
|
||||||
|
build.set_dir(opts.fargs[1])
|
||||||
|
end, {
|
||||||
|
bang = true, nargs = '?', complete = build.list_dirs,
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Create :Build command
|
||||||
|
vim.api.nvim_buf_create_user_command(buffer, 'Build', function(opts)
|
||||||
|
build.run(opts.fargs)
|
||||||
|
end, {
|
||||||
|
bang = true, nargs = '*', complete = build.list_targets,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
return build
|
@ -4,6 +4,7 @@ return {
|
|||||||
'nvim-lua/plenary.nvim',
|
'nvim-lua/plenary.nvim',
|
||||||
'nvim-telescope/telescope-fzy-native.nvim',
|
'nvim-telescope/telescope-fzy-native.nvim',
|
||||||
'nvim-tree/nvim-web-devicons',
|
'nvim-tree/nvim-web-devicons',
|
||||||
|
'axkirillov/easypick.nvim',
|
||||||
},
|
},
|
||||||
config = function()
|
config = function()
|
||||||
local telescope = require('telescope')
|
local telescope = require('telescope')
|
||||||
@ -21,6 +22,9 @@ return {
|
|||||||
['<C-l>'] = 'preview_scrolling_right',
|
['<C-l>'] = 'preview_scrolling_right',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
layout_config = {
|
||||||
|
height = 0.7,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
telescope.load_extension('fzy_native')
|
telescope.load_extension('fzy_native')
|
||||||
@ -33,5 +37,8 @@ return {
|
|||||||
vim.keymap.set('n', '<leader>b', ':Telescope buffers<CR>', opts)
|
vim.keymap.set('n', '<leader>b', ':Telescope buffers<CR>', opts)
|
||||||
vim.keymap.set('n', '<leader>ht', ':Telescope help_tags<CR>', opts)
|
vim.keymap.set('n', '<leader>ht', ':Telescope help_tags<CR>', opts)
|
||||||
|
|
||||||
|
require('easypick').setup({
|
||||||
|
pickers = { },
|
||||||
|
})
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user