WIP implementation of project-based schema
Roughly works but need more work and polishing. The workspace plugin is temporarily disable waiting to be fixed. Now the application does no longer 'chdir' into the project directory and we removed the concept of project's directory (core.project_dir) and project's files (core.project_files). Instead we have always a project that can contain zero, one or many directories or files. No directory is special within a project, there is no longer a concept of project's directory. WIP adapting open-file command to open a directory Crash when adding a file into the project
This commit is contained in:
parent
e8fd785227
commit
0a53425381
|
@ -98,9 +98,20 @@ command.add(nil, {
|
||||||
core.command_view:set_text(text)
|
core.command_view:set_text(text)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
core.command_view:enter("Open File", function(text)
|
core.command_view:enter("Open File", function(text, item)
|
||||||
local filename = system.absolute_path(common.home_expand(text))
|
local filename = common.home_expand(item and item.text or text)
|
||||||
core.root_view:open_doc(core.open_doc(filename))
|
local info = system.get_file_info(filename)
|
||||||
|
print('file', filename, common.serialize(info))
|
||||||
|
if info then
|
||||||
|
if info.type == "file" then
|
||||||
|
core.add_project_file(filename)
|
||||||
|
print('done add_project_file')
|
||||||
|
core.root_view:open_doc(core.open_doc(filename))
|
||||||
|
print('done open_doc')
|
||||||
|
else
|
||||||
|
core.add_project_directory(filename)
|
||||||
|
end
|
||||||
|
end
|
||||||
end, function (text)
|
end, function (text)
|
||||||
return common.home_encode_list(common.path_suggest(common.home_expand(text)))
|
return common.home_encode_list(common.path_suggest(common.home_expand(text)))
|
||||||
end, nil, function(text)
|
end, nil, function(text)
|
||||||
|
@ -172,8 +183,8 @@ command.add(nil, {
|
||||||
end,
|
end,
|
||||||
|
|
||||||
["core:add-directory"] = function()
|
["core:add-directory"] = function()
|
||||||
core.command_view:enter("Add Directory", function(text)
|
core.command_view:enter("Add Directory", function(text, item)
|
||||||
text = common.home_expand(text)
|
text = common.home_expand(item and item.text or text)
|
||||||
local path_stat, err = system.get_file_info(text)
|
local path_stat, err = system.get_file_info(text)
|
||||||
if not path_stat then
|
if not path_stat then
|
||||||
core.error("cannot open %q: %s", text, err)
|
core.error("cannot open %q: %s", text, err)
|
||||||
|
|
|
@ -60,28 +60,14 @@ function core.reschedule_project_scan()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function core.set_project_dir(new_dir, change_project_fn)
|
|
||||||
local chdir_ok = pcall(system.chdir, new_dir)
|
|
||||||
if chdir_ok then
|
|
||||||
if change_project_fn then change_project_fn() end
|
|
||||||
core.project_dir = common.normalize_path(new_dir)
|
|
||||||
core.project_directories = {}
|
|
||||||
core.add_project_directory(new_dir)
|
|
||||||
core.project_files = {}
|
|
||||||
core.project_files_limit = false
|
|
||||||
core.reschedule_project_scan()
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function core.open_folder_project(dir_path_abs)
|
function core.open_folder_project(dir_path_abs)
|
||||||
if core.set_project_dir(dir_path_abs, core.on_quit_project) then
|
-- if core.set_project_dir(dir_path_abs, core.on_quit_project) then
|
||||||
core.root_view:close_all_docviews()
|
core.root_view:close_all_docviews()
|
||||||
update_recents_project("add", dir_path_abs)
|
core.project_entries = {}
|
||||||
core.on_enter_project(dir_path_abs)
|
-- FIXME: check stat info to verify is a directory
|
||||||
end
|
core.add_project_directory(dir_path_abs)
|
||||||
|
update_recents_project("add", dir_path_abs)
|
||||||
|
-- core.on_enter_project(dir_path_abs)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -162,23 +148,21 @@ local function project_scan_thread()
|
||||||
-- get project files and replace previous table if the new table is
|
-- get project files and replace previous table if the new table is
|
||||||
-- different
|
-- different
|
||||||
local i = 1
|
local i = 1
|
||||||
while not core.project_files_limit and i <= #core.project_directories do
|
while not core.project_files_limit and i <= #core.project_entries do
|
||||||
local dir = core.project_directories[i]
|
local dir = core.project_entries[i]
|
||||||
local t, entries_count = get_directory_files(dir.name, "", {}, true)
|
if dir.item.type == 'dir' then
|
||||||
if diff_files(dir.files, t) then
|
local t, entries_count = get_directory_files(dir.name, "", {}, true)
|
||||||
if entries_count > config.max_project_files then
|
if diff_files(dir.files, t) then
|
||||||
core.project_files_limit = true
|
if entries_count > config.max_project_files then
|
||||||
core.status_view:show_message("!", style.accent,
|
core.project_files_limit = true
|
||||||
|
core.status_view:show_message("!", style.accent,
|
||||||
"Too many files in project directory: stopped reading at "..
|
"Too many files in project directory: stopped reading at "..
|
||||||
config.max_project_files.." files. For more information see "..
|
config.max_project_files.." files. For more information see "..
|
||||||
"usage.md at github.com/franko/lite-xl."
|
"usage.md at github.com/franko/lite-xl.")
|
||||||
)
|
end
|
||||||
|
dir.files = t
|
||||||
|
core.redraw = true
|
||||||
end
|
end
|
||||||
dir.files = t
|
|
||||||
core.redraw = true
|
|
||||||
end
|
|
||||||
if dir.name == core.project_dir then
|
|
||||||
core.project_files = dir.files
|
|
||||||
end
|
end
|
||||||
i = i + 1
|
i = i + 1
|
||||||
end
|
end
|
||||||
|
@ -230,12 +214,12 @@ end
|
||||||
|
|
||||||
|
|
||||||
local function project_files_iter(state)
|
local function project_files_iter(state)
|
||||||
local dir = core.project_directories[state.dir_index]
|
local dir = core.project_entries[state.dir_index]
|
||||||
state.file_index = state.file_index + 1
|
state.file_index = state.file_index + 1
|
||||||
while dir and state.file_index > #dir.files do
|
while dir and state.file_index > #dir.files do
|
||||||
state.dir_index = state.dir_index + 1
|
state.dir_index = state.dir_index + 1
|
||||||
state.file_index = 1
|
state.file_index = 1
|
||||||
dir = core.project_directories[state.dir_index]
|
dir = core.project_entries[state.dir_index]
|
||||||
end
|
end
|
||||||
if not dir then return end
|
if not dir then return end
|
||||||
return dir.name, dir.files[state.file_index]
|
return dir.name, dir.files[state.file_index]
|
||||||
|
@ -259,8 +243,8 @@ end
|
||||||
function core.project_files_number()
|
function core.project_files_number()
|
||||||
if not core.project_files_limit then
|
if not core.project_files_limit then
|
||||||
local n = 0
|
local n = 0
|
||||||
for i = 1, #core.project_directories do
|
for i = 1, #core.project_entries do
|
||||||
n = n + #core.project_directories[i].files
|
n = n + #core.project_entries[i].files
|
||||||
end
|
end
|
||||||
return n
|
return n
|
||||||
end
|
end
|
||||||
|
@ -372,12 +356,24 @@ function core.load_user_directory()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function core.add_project_file(path)
|
||||||
|
path = normalize_path(path)
|
||||||
|
table.insert(core.project_entries, {
|
||||||
|
-- type = 'file',
|
||||||
|
name = path,
|
||||||
|
item = {filename = common.basename(path), type = "file", topdir = true},
|
||||||
|
files = {path}
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
function core.add_project_directory(path)
|
function core.add_project_directory(path)
|
||||||
-- top directories has a file-like "item" but the item.filename
|
-- top directories has a file-like "item" but the item.filename
|
||||||
-- will be simply the name of the directory, without its path.
|
-- will be simply the name of the directory, without its path.
|
||||||
-- The field item.topdir will identify it as a top level directory.
|
-- The field item.topdir will identify it as a top level directory.
|
||||||
path = common.normalize_path(path)
|
path = common.normalize_path(path)
|
||||||
table.insert(core.project_directories, {
|
table.insert(core.project_entries, {
|
||||||
|
-- type = 'dir',
|
||||||
name = path,
|
name = path,
|
||||||
item = {filename = common.basename(path), type = "dir", topdir = true},
|
item = {filename = common.basename(path), type = "dir", topdir = true},
|
||||||
files = {}
|
files = {}
|
||||||
|
@ -385,12 +381,12 @@ function core.add_project_directory(path)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function core.remove_project_directory(path)
|
function core.remove_project_entry(path)
|
||||||
-- skip the fist directory because it is the project's directory
|
-- skip the fist directory because it is the project's directory
|
||||||
for i = 2, #core.project_directories do
|
for i = 2, #core.project_entries do
|
||||||
local dir = core.project_directories[i]
|
local dir = core.project_entries[i]
|
||||||
if dir.name == path then
|
if dir.name == path then
|
||||||
table.remove(core.project_directories, i)
|
table.remove(core.project_entries, i)
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -473,12 +469,18 @@ function core.init()
|
||||||
core.log_items = {}
|
core.log_items = {}
|
||||||
core.docs = {}
|
core.docs = {}
|
||||||
core.window_mode = "normal"
|
core.window_mode = "normal"
|
||||||
|
core.project_entries = {}
|
||||||
core.threads = setmetatable({}, { __mode = "k" })
|
core.threads = setmetatable({}, { __mode = "k" })
|
||||||
core.blink_start = system.get_time()
|
core.blink_start = system.get_time()
|
||||||
core.blink_timer = core.blink_start
|
core.blink_timer = core.blink_start
|
||||||
|
|
||||||
local project_dir_abs = system.absolute_path(project_dir)
|
local project_dir_abs = system.absolute_path(project_dir)
|
||||||
local set_project_ok = project_dir_abs and core.set_project_dir(project_dir_abs)
|
if project_dir_abs then
|
||||||
|
core.add_project_directory(project_dir_abs)
|
||||||
|
update_recents_project("add", project_dir_abs)
|
||||||
|
end
|
||||||
|
-- FIXME: below, check if project_dir_abs is ok as a project directory
|
||||||
|
local set_project_ok = project_dir_abs --and core.open_folder_project(project_dir_abs) --core.set_project_dir(project_dir_abs)
|
||||||
if set_project_ok then
|
if set_project_ok then
|
||||||
if project_dir_explicit then
|
if project_dir_explicit then
|
||||||
update_recents_project("add", project_dir_abs)
|
update_recents_project("add", project_dir_abs)
|
||||||
|
@ -487,11 +489,6 @@ function core.init()
|
||||||
if not project_dir_explicit then
|
if not project_dir_explicit then
|
||||||
update_recents_project("remove", project_dir)
|
update_recents_project("remove", project_dir)
|
||||||
end
|
end
|
||||||
project_dir_abs = system.absolute_path(".")
|
|
||||||
if not core.set_project_dir(project_dir_abs) then
|
|
||||||
system.show_fatal_error("Lite XL internal error", "cannot set project directory to cwd")
|
|
||||||
os.exit(1)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
core.redraw = true
|
core.redraw = true
|
||||||
|
|
|
@ -138,7 +138,8 @@ function StatusView:get_items()
|
||||||
style.icon_font, "g",
|
style.icon_font, "g",
|
||||||
style.font, style.dim, self.separator2,
|
style.font, style.dim, self.separator2,
|
||||||
#core.docs, style.text, " / ",
|
#core.docs, style.text, " / ",
|
||||||
#core.project_files, " files"
|
"(NYI) files"
|
||||||
|
--- #core.project_files, " files"
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -64,19 +64,27 @@ function TreeView:get_cached(item, dirname)
|
||||||
local t = dir_cache[cache_name]
|
local t = dir_cache[cache_name]
|
||||||
if not t then
|
if not t then
|
||||||
t = {}
|
t = {}
|
||||||
local basename = common.basename(item.filename)
|
if item.type == 'file' and item.topdir then
|
||||||
if item.topdir then
|
t.filename = item.filename
|
||||||
t.filename = basename
|
|
||||||
t.expanded = true
|
|
||||||
t.depth = 0
|
t.depth = 0
|
||||||
t.abs_filename = dirname
|
t.abs_filename = dirname
|
||||||
|
t.name = item.filename
|
||||||
|
t.type = item.type
|
||||||
else
|
else
|
||||||
t.filename = item.filename
|
local basename = common.basename(item.filename)
|
||||||
t.depth = get_depth(item.filename)
|
if item.topdir then
|
||||||
t.abs_filename = dirname .. PATHSEP .. item.filename
|
t.filename = basename
|
||||||
|
t.expanded = true
|
||||||
|
t.depth = 0
|
||||||
|
t.abs_filename = dirname
|
||||||
|
else
|
||||||
|
t.filename = item.filename
|
||||||
|
t.depth = get_depth(item.filename)
|
||||||
|
t.abs_filename = dirname .. PATHSEP .. item.filename
|
||||||
|
end
|
||||||
|
t.name = basename
|
||||||
|
t.type = item.type
|
||||||
end
|
end
|
||||||
t.name = basename
|
|
||||||
t.type = item.type
|
|
||||||
dir_cache[cache_name] = t
|
dir_cache[cache_name] = t
|
||||||
end
|
end
|
||||||
return t
|
return t
|
||||||
|
@ -102,8 +110,8 @@ end
|
||||||
|
|
||||||
function TreeView:check_cache()
|
function TreeView:check_cache()
|
||||||
-- invalidate cache's skip values if project_files has changed
|
-- invalidate cache's skip values if project_files has changed
|
||||||
for i = 1, #core.project_directories do
|
for i = 1, #core.project_entries do
|
||||||
local dir = core.project_directories[i]
|
local dir = core.project_entries[i]
|
||||||
local last_files = self.last[dir.name]
|
local last_files = self.last[dir.name]
|
||||||
if not last_files then
|
if not last_files then
|
||||||
self.last[dir.name] = dir.files
|
self.last[dir.name] = dir.files
|
||||||
|
@ -126,10 +134,19 @@ function TreeView:each_item()
|
||||||
local w = self.size.x
|
local w = self.size.x
|
||||||
local h = self:get_item_height()
|
local h = self:get_item_height()
|
||||||
|
|
||||||
for k = 1, #core.project_directories do
|
for k = 1, #core.project_entries do
|
||||||
local dir = core.project_directories[k]
|
local dir = core.project_entries[k]
|
||||||
|
if dir.item.type == "file" and dir.item.topdir then
|
||||||
|
print('dir', common.serialize(dir))
|
||||||
|
end
|
||||||
local dir_cached = self:get_cached(dir.item, dir.name)
|
local dir_cached = self:get_cached(dir.item, dir.name)
|
||||||
|
if dir.item.type == "file" and dir.item.topdir then
|
||||||
|
print('cache', common.serialize(dir_cached))
|
||||||
|
end
|
||||||
coroutine.yield(dir_cached, ox, y, w, h)
|
coroutine.yield(dir_cached, ox, y, w, h)
|
||||||
|
if dir.item.type == "file" and dir.item.topdir then
|
||||||
|
print('file topdir yielded')
|
||||||
|
end
|
||||||
count_lines = count_lines + 1
|
count_lines = count_lines + 1
|
||||||
y = y + h
|
y = y + h
|
||||||
local i = 1
|
local i = 1
|
||||||
|
@ -155,6 +172,9 @@ function TreeView:each_item()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end -- while files
|
end -- while files
|
||||||
|
if dir.item.type == "file" and dir.item.topdir then
|
||||||
|
print('loop over files terminated')
|
||||||
|
end
|
||||||
end -- for directories
|
end -- for directories
|
||||||
self.count_lines = count_lines
|
self.count_lines = count_lines
|
||||||
end)
|
end)
|
||||||
|
@ -323,6 +343,7 @@ function TreeView:draw()
|
||||||
|
|
||||||
-- text
|
-- text
|
||||||
x = x + spacing
|
x = x + spacing
|
||||||
|
print('item.name', item.name)
|
||||||
x = common.draw_text(style.font, color, item.name, nil, x, y, 0, h)
|
x = common.draw_text(style.font, color, item.name, nil, x, y, 0, h)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
|
||||||
|
`core.project_directories` => `core.project_entries`
|
||||||
|
- use a new `type` field to indicate it is a directory or a file
|
||||||
|
|
||||||
|
|
||||||
|
`core.{project_dir,project_files}` => removed
|
||||||
|
`core.set_project_dir` => removed
|
||||||
|
|
||||||
|
`core.on_enter_project` => decide what to do
|
||||||
|
|
||||||
|
No longer use `chdir` command.
|
||||||
|
|
||||||
|
## New functions
|
||||||
|
|
||||||
|
`core.add_project_file`
|
||||||
|
|
||||||
|
## Modified functions
|
||||||
|
|
||||||
|
- `core.add_project_directory`
|
||||||
|
- `project_files_iter` local function in `core/init.lua`
|
||||||
|
|
||||||
|
Function `remove_project_directory` is renamed to `remove_project_entry`.
|
||||||
|
|
||||||
|
## Broken
|
||||||
|
|
||||||
|
workspace plugin is not working for the moment.
|
||||||
|
Number of files show in statusview.
|
||||||
|
|
||||||
|
## To be done
|
||||||
|
|
||||||
|
- When using "core:find-file" do not display the full path of the file
|
||||||
|
- FIX the workspace plugin
|
||||||
|
- FIX number of files display in statusview
|
||||||
|
- Add a function to add a file into the project
|
||||||
|
- Add logic to do not show treeview if it contains only a single file
|
||||||
|
- Modify "core:open-file" to accept a directory
|
||||||
|
- Modify "core:open-file" to accept a non-existing file name (new file)
|
||||||
|
|
||||||
|
## Misc observations
|
||||||
|
|
||||||
|
When performing adding directory, pressing enter does not use the item => to be fixed.
|
||||||
|
The function `system.chdir` is no longer used and could be removed, in theory.
|
Loading…
Reference in New Issue