aboutsummaryrefslogtreecommitdiff
path: root/lua/cmake-explorer/project.lua
blob: 967ec1b779fdb068eee6062bc4809fcacff8272c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
local config = require("cmake-explorer.config")
local globals = require("cmake-explorer.globals")
local Build = require("cmake-explorer.build")
local Path = require("plenary.path")
local Scandir = require("plenary.scandir")
local utils = require("cmake-explorer.utils")

local get_builds_in_dir = function(path)
	local ret = {}
	-- add to builds directories which accept is_build_dir()
	local candidates = Scandir.scan_dir(path, { hidden = false, only_dirs = true, depth = 0, silent = true })
	for _, v in ipairs(candidates) do
		if Build.is_build_dir(v) then
			local b = Build:new(v)
			table.insert(ret, b)
		end
	end
	return ret
end

local set_current_build = function(builds, filter)
	local filter_func
	if type(filter) == "number" then
		if filter >= 1 and filter <= #builds then
			return builds[filter]
		else
			print("set_current_build. index out of range. set to first")
			return builds[1]
		end
	elseif type(filter) == "string" then
		filter_func = function(v)
			return v:build_type() == filter
		end
	elseif type(filter) == "function" then
		filter_func = filter
	else
		return builds[1]
	end
	for _, v in ipairs(builds) do
		if filter_func(v) == true then
			return v
		end
	end
	return builds[1]
end

local Project = {}

Project.__index = Project

function Project:new(o)
	o = o or {}

	local path
	if type(o) == "string" then
		path = o
	elseif type(o) == "table" and o.path then
		path = o.path
	else
		return
	end

	if not Path:new(path, "CMakeLists.txt"):exists() then
		return
	end

	local obj = {
		path = Path:new(path),
		builds = nil,
		current_build = nil,
	}
	obj.builds = get_builds_in_dir(path)
	obj.current_build = set_current_build(obj.builds, config.build_types[1])
	setmetatable(obj, Project)
	return obj
end

-- finds build with passed params, creates new build if not found
function Project:append_build(params)
	local build_dir = (self.path / Build.name(params)):absolute()
	for _, v in ipairs(self.builds) do
		if v.path:absolute() == build_dir then
			print("append_build. build found")
			return v
		end
	end
	print("append_build. new build")
	table.insert(self.builds, Build:new(build_dir))
	return self.builds[#self.builds]
end

function Project:symlink_compile_commands()
	local src = (self.current_build.path / "compile_commands.json")
	if src:exists() then
		vim.cmd(
			'silent exec "!'
				.. config.cmake_cmd
				.. " -E create_symlink "
				.. src:absolute()
				.. " "
				.. (self.path / "compile_commands.json"):absolute()
				.. '"'
		)
	end
end

function Project:list_build_dirs_names()
	local ret = {}
	for _, v in ipairs(self.builds) do
		table.insert(ret, v.path:absolute())
	end
	return ret
end

function Project:configure(params)
	params = params or {}

	self.current_build = self:append_build(params)
	local args = vim.tbl_deep_extend("keep", params.args or {}, config.options or {})
	table.insert(args, "-G" .. (params.generator or globals.generators[1]))
	table.insert(args, "-DCMAKE_BUILD_TYPE=" .. (params.build_type or config.build_types[1]))
	table.insert(args, "-S" .. self.path:absolute())
	table.insert(args, "-B" .. self.current_build.path:absolute())
	return {
		cmd = config.cmake_cmd,
		args = args,
		after_success = function()
			self:symlink_compile_commands()
		end,
	}
end

return Project