Compare commits
6 Commits
amiga2.1
...
fix-networ
Author | SHA1 | Date |
---|---|---|
Francesco Abbate | 719839d299 | |
Francesco Abbate | 1794765f07 | |
Francesco Abbate | bed103b7a6 | |
Francesco Abbate | 80db3cb027 | |
Francesco Abbate | a0f4ac93e1 | |
Francesco Abbate | 43fc35d7dc |
|
@ -280,24 +280,61 @@ local function split_on_slash(s, sep_pattern)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function common.normalize_path(filename)
|
-- The filename argument given to the function is supposed to
|
||||||
|
-- come from system.absolute_path and as such should be an
|
||||||
|
-- absolute path without . or .. elements.
|
||||||
|
-- This function exists because on Windows the drive letter returned
|
||||||
|
-- by system.absolute_path is sometimes with a lower case and sometimes
|
||||||
|
-- with an upper case to we normalize to upper case.
|
||||||
|
function common.normalize_volume(filename)
|
||||||
if not filename then return end
|
if not filename then return end
|
||||||
|
if PATHSEP == '\\' then
|
||||||
|
local drive, rem = filename:match('^([a-zA-Z]:\\)(.*)')
|
||||||
|
if drive then
|
||||||
|
return drive:upper() .. rem
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return filename
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function common.normalize_path(filename)
|
||||||
|
if not filename then return end
|
||||||
|
local volume
|
||||||
if PATHSEP == '\\' then
|
if PATHSEP == '\\' then
|
||||||
filename = filename:gsub('[/\\]', '\\')
|
filename = filename:gsub('[/\\]', '\\')
|
||||||
local drive, rem = filename:match('^([a-zA-Z])(:.*)')
|
local drive, rem = filename:match('^([a-zA-Z]:\\)(.*)')
|
||||||
filename = drive and drive:upper() .. rem or filename
|
if drive then
|
||||||
|
volume, filename = drive:upper(), rem
|
||||||
|
else
|
||||||
|
drive, rem = filename:match('^(\\\\[^\\]+\\[^\\]+\\)(.*)')
|
||||||
|
if drive then
|
||||||
|
volume, filename = drive, rem
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local relpath = filename:match('^/(.+)')
|
||||||
|
if relpath then
|
||||||
|
volume, filename = "/", relpath
|
||||||
|
end
|
||||||
end
|
end
|
||||||
local parts = split_on_slash(filename, PATHSEP)
|
local parts = split_on_slash(filename, PATHSEP)
|
||||||
local accu = {}
|
local accu = {}
|
||||||
for _, part in ipairs(parts) do
|
for _, part in ipairs(parts) do
|
||||||
if part == '..' and #accu > 0 and accu[#accu] ~= ".." then
|
if part == '..' then
|
||||||
table.remove(accu)
|
if #accu > 0 and accu[#accu] ~= ".." then
|
||||||
|
table.remove(accu)
|
||||||
|
elseif volume then
|
||||||
|
error("invalid path " .. volume .. filename)
|
||||||
|
else
|
||||||
|
table.insert(accu, part)
|
||||||
|
end
|
||||||
elseif part ~= '.' then
|
elseif part ~= '.' then
|
||||||
table.insert(accu, part)
|
table.insert(accu, part)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local npath = table.concat(accu, PATHSEP)
|
local npath = table.concat(accu, PATHSEP)
|
||||||
return npath == "" and PATHSEP or npath
|
return (volume or "") .. (npath == "" and PATHSEP or npath)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ end
|
||||||
|
|
||||||
|
|
||||||
local function update_recents_project(action, dir_path_abs)
|
local function update_recents_project(action, dir_path_abs)
|
||||||
local dirname = common.normalize_path(dir_path_abs)
|
local dirname = common.normalize_volume(dir_path_abs)
|
||||||
if not dirname then return end
|
if not dirname then return end
|
||||||
local recents = core.recent_projects
|
local recents = core.recent_projects
|
||||||
local n = #recents
|
local n = #recents
|
||||||
|
@ -56,7 +56,7 @@ function core.set_project_dir(new_dir, change_project_fn)
|
||||||
local chdir_ok = pcall(system.chdir, new_dir)
|
local chdir_ok = pcall(system.chdir, new_dir)
|
||||||
if chdir_ok then
|
if chdir_ok then
|
||||||
if change_project_fn then change_project_fn() end
|
if change_project_fn then change_project_fn() end
|
||||||
core.project_dir = common.normalize_path(new_dir)
|
core.project_dir = common.normalize_volume(new_dir)
|
||||||
core.project_directories = {}
|
core.project_directories = {}
|
||||||
core.add_project_directory(new_dir)
|
core.add_project_directory(new_dir)
|
||||||
return true
|
return true
|
||||||
|
@ -106,6 +106,15 @@ local function get_project_file_info(root, file)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Predicate function to inhibit directory recursion in get_directory_files
|
||||||
|
-- based on a time limit and the number of files.
|
||||||
|
local function timed_max_files_pred(dir, filename, entries_count, t_elapsed)
|
||||||
|
local n_limit = entries_count <= config.max_project_files
|
||||||
|
local t_limit = t_elapsed < 20 / config.fps
|
||||||
|
return n_limit and t_limit and core.project_subdir_is_shown(dir, filename)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- "root" will by an absolute path without trailing '/'
|
-- "root" will by an absolute path without trailing '/'
|
||||||
-- "path" will be a path starting with '/' and without trailing '/'
|
-- "path" will be a path starting with '/' and without trailing '/'
|
||||||
-- or the empty string.
|
-- or the empty string.
|
||||||
|
@ -114,12 +123,13 @@ end
|
||||||
-- When recursing "root" will always be the same, only "path" will change.
|
-- When recursing "root" will always be the same, only "path" will change.
|
||||||
-- Returns a list of file "items". In eash item the "filename" will be the
|
-- Returns a list of file "items". In eash item the "filename" will be the
|
||||||
-- complete file path relative to "root" *without* the trailing '/'.
|
-- complete file path relative to "root" *without* the trailing '/'.
|
||||||
local function get_directory_files(dir, root, path, t, begin_hook, max_files)
|
local function get_directory_files(dir, root, path, t, entries_count, recurse_pred, begin_hook)
|
||||||
if begin_hook then begin_hook() end
|
if begin_hook then begin_hook() end
|
||||||
|
local t0 = system.get_time()
|
||||||
local all = system.list_dir(root .. path) or {}
|
local all = system.list_dir(root .. path) or {}
|
||||||
|
local t_elapsed = system.get_time() - t0
|
||||||
local dirs, files = {}, {}
|
local dirs, files = {}, {}
|
||||||
|
|
||||||
local entries_count = 0
|
|
||||||
for _, file in ipairs(all) do
|
for _, file in ipairs(all) do
|
||||||
local info = get_project_file_info(root, path .. PATHSEP .. file)
|
local info = get_project_file_info(root, path .. PATHSEP .. file)
|
||||||
if info then
|
if info then
|
||||||
|
@ -128,13 +138,16 @@ local function get_directory_files(dir, root, path, t, begin_hook, max_files)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local recurse_complete = true
|
||||||
table.sort(dirs, compare_file)
|
table.sort(dirs, compare_file)
|
||||||
for _, f in ipairs(dirs) do
|
for _, f in ipairs(dirs) do
|
||||||
table.insert(t, f)
|
table.insert(t, f)
|
||||||
if (not max_files or entries_count <= max_files) and core.project_subdir_is_shown(dir, f.filename) then
|
if recurse_pred(dir, f.filename, entries_count, t_elapsed) then
|
||||||
local sub_limit = max_files and max_files - entries_count
|
local _, complete, n = get_directory_files(dir, root, PATHSEP .. f.filename, t, entries_count, recurse_pred, begin_hook)
|
||||||
local _, n = get_directory_files(dir, root, PATHSEP .. f.filename, t, begin_hook, sub_limit)
|
recurse_complete = recurse_complete and complete
|
||||||
entries_count = entries_count + n
|
entries_count = n
|
||||||
|
else
|
||||||
|
recurse_complete = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -143,7 +156,7 @@ local function get_directory_files(dir, root, path, t, begin_hook, max_files)
|
||||||
table.insert(t, f)
|
table.insert(t, f)
|
||||||
end
|
end
|
||||||
|
|
||||||
return t, entries_count
|
return t, recurse_complete, entries_count
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -165,26 +178,28 @@ function core.project_subdir_is_shown(dir, filename)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local function show_max_files_warning()
|
local function show_max_files_warning(dir)
|
||||||
core.status_view:show_message("!", style.accent,
|
local message = dir.slow_filesystem and
|
||||||
|
"Filesystem is too slow: project files will not be indexed." or
|
||||||
"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."
|
||||||
)
|
core.status_view:show_message("!", style.accent, message)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Populate a project folder top directory by scanning the filesystem.
|
-- Populate a project folder top directory by scanning the filesystem.
|
||||||
local function scan_project_folder(index)
|
local function scan_project_folder(index)
|
||||||
local dir = core.project_directories[index]
|
local dir = core.project_directories[index]
|
||||||
local t, entries_count = get_directory_files(dir, dir.name, "", {}, nil, config.max_project_files)
|
local t, complete, entries_count = get_directory_files(dir, dir.name, "", {}, 0, timed_max_files_pred)
|
||||||
if entries_count > config.max_project_files then
|
if not complete then
|
||||||
|
dir.slow_filesystem = not complete and (entries_count <= config.max_project_files)
|
||||||
dir.files_limit = true
|
dir.files_limit = true
|
||||||
-- Watch non-recursively on Linux only.
|
-- Watch non-recursively on Linux only.
|
||||||
-- The reason is recursively watching with dmon on linux
|
-- The reason is recursively watching with dmon on linux
|
||||||
-- doesn't work on very large directories.
|
-- doesn't work on very large directories.
|
||||||
dir.watch_id = system.watch_dir(dir.name, PLATFORM ~= "Linux")
|
dir.watch_id = system.watch_dir(dir.name, PLATFORM ~= "Linux")
|
||||||
if core.status_view then -- May be not yet initialized.
|
if core.status_view then -- May be not yet initialized.
|
||||||
show_max_files_warning()
|
show_max_files_warning(dir)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
dir.watch_id = system.watch_dir(dir.name, true)
|
dir.watch_id = system.watch_dir(dir.name, true)
|
||||||
|
@ -198,7 +213,7 @@ 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_volume(path)
|
||||||
local dir = {
|
local dir = {
|
||||||
name = path,
|
name = path,
|
||||||
item = {filename = common.basename(path), type = "dir", topdir = true},
|
item = {filename = common.basename(path), type = "dir", topdir = true},
|
||||||
|
@ -298,7 +313,7 @@ local function project_subdir_bounds(dir, filename)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function rescan_project_subdir(dir, filename_rooted)
|
local function rescan_project_subdir(dir, filename_rooted)
|
||||||
local new_files = get_directory_files(dir, dir.name, filename_rooted, {}, coroutine.yield)
|
local new_files = get_directory_files(dir, dir.name, filename_rooted, {}, 0, core.project_subdir_is_shown, coroutine.yield)
|
||||||
local index, n = 0, #dir.files
|
local index, n = 0, #dir.files
|
||||||
if filename_rooted ~= "" then
|
if filename_rooted ~= "" then
|
||||||
local filename = strip_leading_path(filename_rooted)
|
local filename = strip_leading_path(filename_rooted)
|
||||||
|
@ -316,7 +331,7 @@ end
|
||||||
function core.update_project_subdir(dir, filename, expanded)
|
function core.update_project_subdir(dir, filename, expanded)
|
||||||
local index, n, file = project_subdir_bounds(dir, filename)
|
local index, n, file = project_subdir_bounds(dir, filename)
|
||||||
if index then
|
if index then
|
||||||
local new_files = expanded and get_directory_files(dir, dir.name, PATHSEP .. filename, {}) or {}
|
local new_files = expanded and get_directory_files(dir, dir.name, PATHSEP .. filename, {}, 0, core.project_subdir_is_shown) or {}
|
||||||
files_list_replace(dir.files, index, n, new_files)
|
files_list_replace(dir.files, index, n, new_files)
|
||||||
dir.is_dirty = true
|
dir.is_dirty = true
|
||||||
return true
|
return true
|
||||||
|
@ -572,9 +587,9 @@ function core.init()
|
||||||
Doc = require "core.doc"
|
Doc = require "core.doc"
|
||||||
|
|
||||||
if PATHSEP == '\\' then
|
if PATHSEP == '\\' then
|
||||||
USERDIR = common.normalize_path(USERDIR)
|
USERDIR = common.normalize_volume(USERDIR)
|
||||||
DATADIR = common.normalize_path(DATADIR)
|
DATADIR = common.normalize_volume(DATADIR)
|
||||||
EXEDIR = common.normalize_path(EXEDIR)
|
EXEDIR = common.normalize_volume(EXEDIR)
|
||||||
end
|
end
|
||||||
|
|
||||||
do
|
do
|
||||||
|
@ -673,7 +688,7 @@ function core.init()
|
||||||
-- We assume we have just a single project directory here. Now that StatusView
|
-- We assume we have just a single project directory here. Now that StatusView
|
||||||
-- is there show max files warning if needed.
|
-- is there show max files warning if needed.
|
||||||
if core.project_directories[1].files_limit then
|
if core.project_directories[1].files_limit then
|
||||||
show_max_files_warning()
|
show_max_files_warning(core.project_directories[1])
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, filename in ipairs(files) do
|
for _, filename in ipairs(files) do
|
||||||
|
|
|
@ -412,7 +412,7 @@ end
|
||||||
-- axis are swapped; this function lets us use the same code for both
|
-- axis are swapped; this function lets us use the same code for both
|
||||||
local function calc_split_sizes(self, x, y, x1, x2, y1, y2)
|
local function calc_split_sizes(self, x, y, x1, x2, y1, y2)
|
||||||
local ds = ((x1 and x1 < 1) or (x2 and x2 < 1)) and 0 or style.divider_size
|
local ds = ((x1 and x1 < 1) or (x2 and x2 < 1)) and 0 or style.divider_size
|
||||||
local n = math.floor(x1 and x1 + ds or (x2 and self.size[x] - x2 or self.size[x] * self.divider))
|
local n = x1 and x1 + ds or (x2 and self.size[x] - x2 or math.floor(self.size[x] * self.divider))
|
||||||
self.a.position[x] = self.position[x]
|
self.a.position[x] = self.position[x]
|
||||||
self.a.position[y] = self.position[y]
|
self.a.position[y] = self.position[y]
|
||||||
self.a.size[x] = n - ds
|
self.a.size[x] = n - ds
|
||||||
|
@ -675,6 +675,10 @@ end
|
||||||
|
|
||||||
|
|
||||||
function Node:resize(axis, value)
|
function Node:resize(axis, value)
|
||||||
|
-- the application works fine with non-integer values but to have pixel-perfect
|
||||||
|
-- placements of view elements, like the scrollbar, we round the value to be
|
||||||
|
-- an integer.
|
||||||
|
value = math.floor(value)
|
||||||
if self.type == 'leaf' then
|
if self.type == 'leaf' then
|
||||||
-- If it is not locked we don't accept the
|
-- If it is not locked we don't accept the
|
||||||
-- resize operation here because for proportional panes the resize is
|
-- resize operation here because for proportional panes the resize is
|
||||||
|
|
Loading…
Reference in New Issue