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
ea3a7e81be
commit
ac0dba18de
|
@ -90,8 +90,20 @@ command.add(nil, {
|
||||||
if view.doc and view.doc.abs_filename then
|
if view.doc and view.doc.abs_filename then
|
||||||
core.command_view:set_text(common.home_encode(view.doc.abs_filename))
|
core.command_view:set_text(common.home_encode(view.doc.abs_filename))
|
||||||
end
|
end
|
||||||
core.command_view:enter("Open File", function(text)
|
core.command_view:enter("Open File", function(text, item)
|
||||||
core.root_view:open_doc(core.open_doc(common.home_expand(text)))
|
local filename = common.home_expand(item and item.text or text)
|
||||||
|
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)
|
||||||
|
@ -163,8 +175,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)
|
||||||
|
|
|
@ -58,27 +58,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.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
|
||||||
|
|
||||||
|
|
||||||
|
@ -158,23 +145,22 @@ local function project_scan_thread()
|
||||||
while true do
|
while true do
|
||||||
-- 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
|
||||||
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 t, entries_count = get_files(dir.name, "")
|
if dir.item.type == 'dir' then
|
||||||
if diff_files(dir.files, t) then
|
local t, entries_count = get_files(dir.name, "")
|
||||||
if entries_count > config.max_project_files then
|
if diff_files(dir.files, t) then
|
||||||
core.status_view:show_message("!", style.accent,
|
if entries_count > config.max_project_files then
|
||||||
"Too many files in project directory: stopping reading at "..
|
core.status_view:show_message("!", style.accent,
|
||||||
config.max_project_files.." files according to config.max_project_files. "..
|
"Too many files in project directory: stopping reading at "..
|
||||||
"Either tweak this variable, or ignore certain files/directories by "..
|
config.max_project_files.." files according to config.max_project_files. "..
|
||||||
"using the config.ignore_files variable in your user plugin or "..
|
"Either tweak this variable, or ignore certain files/directories by "..
|
||||||
"project config.")
|
"using the config.ignore_files variable in your user plugin or "..
|
||||||
|
"project config.")
|
||||||
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -185,12 +171,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]
|
||||||
|
@ -205,8 +191,8 @@ end
|
||||||
|
|
||||||
function core.project_files_number()
|
function core.project_files_number()
|
||||||
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
|
||||||
|
@ -317,12 +303,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 = {}
|
||||||
|
@ -330,12 +328,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
|
||||||
|
@ -402,12 +400,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)
|
||||||
|
@ -416,11 +420,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
|
||||||
|
@ -95,8 +103,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
|
||||||
|
@ -121,10 +129,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
|
||||||
|
@ -150,6 +167,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)
|
||||||
|
@ -310,6 +330,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