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
|
||||
core.command_view:set_text(common.home_encode(view.doc.abs_filename))
|
||||
end
|
||||
core.command_view:enter("Open File", function(text)
|
||||
core.root_view:open_doc(core.open_doc(common.home_expand(text)))
|
||||
core.command_view:enter("Open File", function(text, item)
|
||||
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)
|
||||
return common.home_encode_list(common.path_suggest(common.home_expand(text)))
|
||||
end, nil, function(text)
|
||||
|
@ -163,8 +175,8 @@ command.add(nil, {
|
|||
end,
|
||||
|
||||
["core:add-directory"] = function()
|
||||
core.command_view:enter("Add Directory", function(text)
|
||||
text = common.home_expand(text)
|
||||
core.command_view:enter("Add Directory", function(text, item)
|
||||
text = common.home_expand(item and item.text or text)
|
||||
local path_stat, err = system.get_file_info(text)
|
||||
if not path_stat then
|
||||
core.error("cannot open %q: %s", text, err)
|
||||
|
|
|
@ -58,27 +58,14 @@ function core.reschedule_project_scan()
|
|||
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)
|
||||
if core.set_project_dir(dir_path_abs, core.on_quit_project) then
|
||||
core.root_view:close_all_docviews()
|
||||
update_recents_project("add", dir_path_abs)
|
||||
core.on_enter_project(dir_path_abs)
|
||||
end
|
||||
-- if core.set_project_dir(dir_path_abs, core.on_quit_project) then
|
||||
core.root_view:close_all_docviews()
|
||||
core.project_entries = {}
|
||||
-- FIXME: check stat info to verify is a directory
|
||||
core.add_project_directory(dir_path_abs)
|
||||
update_recents_project("add", dir_path_abs)
|
||||
-- core.on_enter_project(dir_path_abs)
|
||||
end
|
||||
|
||||
|
||||
|
@ -158,23 +145,22 @@ local function project_scan_thread()
|
|||
while true do
|
||||
-- get project files and replace previous table if the new table is
|
||||
-- different
|
||||
for i = 1, #core.project_directories do
|
||||
local dir = core.project_directories[i]
|
||||
local t, entries_count = get_files(dir.name, "")
|
||||
if diff_files(dir.files, t) then
|
||||
if entries_count > config.max_project_files then
|
||||
core.status_view:show_message("!", style.accent,
|
||||
"Too many files in project directory: stopping reading at "..
|
||||
config.max_project_files.." files according to config.max_project_files. "..
|
||||
"Either tweak this variable, or ignore certain files/directories by "..
|
||||
"using the config.ignore_files variable in your user plugin or "..
|
||||
"project config.")
|
||||
for i = 1, #core.project_entries do
|
||||
local dir = core.project_entries[i]
|
||||
if dir.item.type == 'dir' then
|
||||
local t, entries_count = get_files(dir.name, "")
|
||||
if diff_files(dir.files, t) then
|
||||
if entries_count > config.max_project_files then
|
||||
core.status_view:show_message("!", style.accent,
|
||||
"Too many files in project directory: stopping reading at "..
|
||||
config.max_project_files.." files according to config.max_project_files. "..
|
||||
"Either tweak this variable, or ignore certain files/directories by "..
|
||||
"using the config.ignore_files variable in your user plugin or "..
|
||||
"project config.")
|
||||
end
|
||||
dir.files = t
|
||||
core.redraw = true
|
||||
end
|
||||
dir.files = t
|
||||
core.redraw = true
|
||||
end
|
||||
if dir.name == core.project_dir then
|
||||
core.project_files = dir.files
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -185,12 +171,12 @@ end
|
|||
|
||||
|
||||
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
|
||||
while dir and state.file_index > #dir.files do
|
||||
state.dir_index = state.dir_index + 1
|
||||
state.file_index = 1
|
||||
dir = core.project_directories[state.dir_index]
|
||||
dir = core.project_entries[state.dir_index]
|
||||
end
|
||||
if not dir then return end
|
||||
return dir.name, dir.files[state.file_index]
|
||||
|
@ -205,8 +191,8 @@ end
|
|||
|
||||
function core.project_files_number()
|
||||
local n = 0
|
||||
for i = 1, #core.project_directories do
|
||||
n = n + #core.project_directories[i].files
|
||||
for i = 1, #core.project_entries do
|
||||
n = n + #core.project_entries[i].files
|
||||
end
|
||||
return n
|
||||
end
|
||||
|
@ -317,12 +303,24 @@ function core.load_user_directory()
|
|||
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)
|
||||
-- top directories has a file-like "item" but the item.filename
|
||||
-- will be simply the name of the directory, without its path.
|
||||
-- The field item.topdir will identify it as a top level directory.
|
||||
path = common.normalize_path(path)
|
||||
table.insert(core.project_directories, {
|
||||
table.insert(core.project_entries, {
|
||||
-- type = 'dir',
|
||||
name = path,
|
||||
item = {filename = common.basename(path), type = "dir", topdir = true},
|
||||
files = {}
|
||||
|
@ -330,12 +328,12 @@ function core.add_project_directory(path)
|
|||
end
|
||||
|
||||
|
||||
function core.remove_project_directory(path)
|
||||
function core.remove_project_entry(path)
|
||||
-- skip the fist directory because it is the project's directory
|
||||
for i = 2, #core.project_directories do
|
||||
local dir = core.project_directories[i]
|
||||
for i = 2, #core.project_entries do
|
||||
local dir = core.project_entries[i]
|
||||
if dir.name == path then
|
||||
table.remove(core.project_directories, i)
|
||||
table.remove(core.project_entries, i)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
@ -402,12 +400,18 @@ function core.init()
|
|||
core.log_items = {}
|
||||
core.docs = {}
|
||||
core.window_mode = "normal"
|
||||
core.project_entries = {}
|
||||
core.threads = setmetatable({}, { __mode = "k" })
|
||||
core.blink_start = system.get_time()
|
||||
core.blink_timer = core.blink_start
|
||||
|
||||
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 project_dir_explicit then
|
||||
update_recents_project("add", project_dir_abs)
|
||||
|
@ -416,11 +420,6 @@ function core.init()
|
|||
if not project_dir_explicit then
|
||||
update_recents_project("remove", project_dir)
|
||||
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
|
||||
|
||||
core.redraw = true
|
||||
|
|
|
@ -138,7 +138,8 @@ function StatusView:get_items()
|
|||
style.icon_font, "g",
|
||||
style.font, style.dim, self.separator2,
|
||||
#core.docs, style.text, " / ",
|
||||
#core.project_files, " files"
|
||||
"(NYI) files"
|
||||
--- #core.project_files, " files"
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -64,19 +64,27 @@ function TreeView:get_cached(item, dirname)
|
|||
local t = dir_cache[cache_name]
|
||||
if not t then
|
||||
t = {}
|
||||
local basename = common.basename(item.filename)
|
||||
if item.topdir then
|
||||
t.filename = basename
|
||||
t.expanded = true
|
||||
if item.type == 'file' and item.topdir then
|
||||
t.filename = item.filename
|
||||
t.depth = 0
|
||||
t.abs_filename = dirname
|
||||
t.name = item.filename
|
||||
t.type = item.type
|
||||
else
|
||||
t.filename = item.filename
|
||||
t.depth = get_depth(item.filename)
|
||||
t.abs_filename = dirname .. PATHSEP .. item.filename
|
||||
local basename = common.basename(item.filename)
|
||||
if item.topdir then
|
||||
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
|
||||
t.name = basename
|
||||
t.type = item.type
|
||||
dir_cache[cache_name] = t
|
||||
end
|
||||
return t
|
||||
|
@ -95,8 +103,8 @@ end
|
|||
|
||||
function TreeView:check_cache()
|
||||
-- invalidate cache's skip values if project_files has changed
|
||||
for i = 1, #core.project_directories do
|
||||
local dir = core.project_directories[i]
|
||||
for i = 1, #core.project_entries do
|
||||
local dir = core.project_entries[i]
|
||||
local last_files = self.last[dir.name]
|
||||
if not last_files then
|
||||
self.last[dir.name] = dir.files
|
||||
|
@ -121,10 +129,19 @@ function TreeView:each_item()
|
|||
local w = self.size.x
|
||||
local h = self:get_item_height()
|
||||
|
||||
for k = 1, #core.project_directories do
|
||||
local dir = core.project_directories[k]
|
||||
for k = 1, #core.project_entries do
|
||||
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)
|
||||
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)
|
||||
if dir.item.type == "file" and dir.item.topdir then
|
||||
print('file topdir yielded')
|
||||
end
|
||||
count_lines = count_lines + 1
|
||||
y = y + h
|
||||
local i = 1
|
||||
|
@ -150,6 +167,9 @@ function TreeView:each_item()
|
|||
end
|
||||
end
|
||||
end -- while files
|
||||
if dir.item.type == "file" and dir.item.topdir then
|
||||
print('loop over files terminated')
|
||||
end
|
||||
end -- for directories
|
||||
self.count_lines = count_lines
|
||||
end)
|
||||
|
@ -310,6 +330,7 @@ function TreeView:draw()
|
|||
|
||||
-- text
|
||||
x = x + spacing
|
||||
print('item.name', item.name)
|
||||
x = common.draw_text(style.font, color, item.name, nil, x, y, 0, h)
|
||||
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