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
|
||||
|
||||
|
||||
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 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
|
||||
filename = filename:gsub('[/\\]', '\\')
|
||||
local drive, rem = filename:match('^([a-zA-Z])(:.*)')
|
||||
filename = drive and drive:upper() .. rem or filename
|
||||
local drive, rem = filename:match('^([a-zA-Z]:\\)(.*)')
|
||||
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
|
||||
local parts = split_on_slash(filename, PATHSEP)
|
||||
local accu = {}
|
||||
for _, part in ipairs(parts) do
|
||||
if part == '..' and #accu > 0 and accu[#accu] ~= ".." then
|
||||
if part == '..' then
|
||||
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
|
||||
table.insert(accu, part)
|
||||
end
|
||||
end
|
||||
local npath = table.concat(accu, PATHSEP)
|
||||
return npath == "" and PATHSEP or npath
|
||||
return (volume or "") .. (npath == "" and PATHSEP or npath)
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ end
|
|||
|
||||
|
||||
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
|
||||
local recents = core.recent_projects
|
||||
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)
|
||||
if chdir_ok then
|
||||
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.add_project_directory(new_dir)
|
||||
return true
|
||||
|
@ -106,6 +106,15 @@ local function get_project_file_info(root, file)
|
|||
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 '/'
|
||||
-- "path" will be a path starting with '/' and without trailing '/'
|
||||
-- or the empty string.
|
||||
|
@ -114,12 +123,13 @@ end
|
|||
-- 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
|
||||
-- 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
|
||||
local t0 = system.get_time()
|
||||
local all = system.list_dir(root .. path) or {}
|
||||
local t_elapsed = system.get_time() - t0
|
||||
local dirs, files = {}, {}
|
||||
|
||||
local entries_count = 0
|
||||
for _, file in ipairs(all) do
|
||||
local info = get_project_file_info(root, path .. PATHSEP .. file)
|
||||
if info then
|
||||
|
@ -128,13 +138,16 @@ local function get_directory_files(dir, root, path, t, begin_hook, max_files)
|
|||
end
|
||||
end
|
||||
|
||||
local recurse_complete = true
|
||||
table.sort(dirs, compare_file)
|
||||
for _, f in ipairs(dirs) do
|
||||
table.insert(t, f)
|
||||
if (not max_files or entries_count <= max_files) and core.project_subdir_is_shown(dir, f.filename) then
|
||||
local sub_limit = max_files and max_files - entries_count
|
||||
local _, n = get_directory_files(dir, root, PATHSEP .. f.filename, t, begin_hook, sub_limit)
|
||||
entries_count = entries_count + n
|
||||
if recurse_pred(dir, f.filename, entries_count, t_elapsed) then
|
||||
local _, complete, n = get_directory_files(dir, root, PATHSEP .. f.filename, t, entries_count, recurse_pred, begin_hook)
|
||||
recurse_complete = recurse_complete and complete
|
||||
entries_count = n
|
||||
else
|
||||
recurse_complete = false
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -143,7 +156,7 @@ local function get_directory_files(dir, root, path, t, begin_hook, max_files)
|
|||
table.insert(t, f)
|
||||
end
|
||||
|
||||
return t, entries_count
|
||||
return t, recurse_complete, entries_count
|
||||
end
|
||||
|
||||
|
||||
|
@ -165,26 +178,28 @@ function core.project_subdir_is_shown(dir, filename)
|
|||
end
|
||||
|
||||
|
||||
local function show_max_files_warning()
|
||||
core.status_view:show_message("!", style.accent,
|
||||
local function show_max_files_warning(dir)
|
||||
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 "..
|
||||
config.max_project_files.." files. For more information see "..
|
||||
"usage.md at github.com/franko/lite-xl."
|
||||
)
|
||||
core.status_view:show_message("!", style.accent, message)
|
||||
end
|
||||
|
||||
-- Populate a project folder top directory by scanning the filesystem.
|
||||
local function scan_project_folder(index)
|
||||
local dir = core.project_directories[index]
|
||||
local t, entries_count = get_directory_files(dir, dir.name, "", {}, nil, config.max_project_files)
|
||||
if entries_count > config.max_project_files then
|
||||
local t, complete, entries_count = get_directory_files(dir, dir.name, "", {}, 0, timed_max_files_pred)
|
||||
if not complete then
|
||||
dir.slow_filesystem = not complete and (entries_count <= config.max_project_files)
|
||||
dir.files_limit = true
|
||||
-- Watch non-recursively on Linux only.
|
||||
-- The reason is recursively watching with dmon on linux
|
||||
-- doesn't work on very large directories.
|
||||
dir.watch_id = system.watch_dir(dir.name, PLATFORM ~= "Linux")
|
||||
if core.status_view then -- May be not yet initialized.
|
||||
show_max_files_warning()
|
||||
show_max_files_warning(dir)
|
||||
end
|
||||
else
|
||||
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
|
||||
-- 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)
|
||||
path = common.normalize_volume(path)
|
||||
local dir = {
|
||||
name = path,
|
||||
item = {filename = common.basename(path), type = "dir", topdir = true},
|
||||
|
@ -298,7 +313,7 @@ local function project_subdir_bounds(dir, filename)
|
|||
end
|
||||
|
||||
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
|
||||
if filename_rooted ~= "" then
|
||||
local filename = strip_leading_path(filename_rooted)
|
||||
|
@ -316,7 +331,7 @@ end
|
|||
function core.update_project_subdir(dir, filename, expanded)
|
||||
local index, n, file = project_subdir_bounds(dir, filename)
|
||||
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)
|
||||
dir.is_dirty = true
|
||||
return true
|
||||
|
@ -572,9 +587,9 @@ function core.init()
|
|||
Doc = require "core.doc"
|
||||
|
||||
if PATHSEP == '\\' then
|
||||
USERDIR = common.normalize_path(USERDIR)
|
||||
DATADIR = common.normalize_path(DATADIR)
|
||||
EXEDIR = common.normalize_path(EXEDIR)
|
||||
USERDIR = common.normalize_volume(USERDIR)
|
||||
DATADIR = common.normalize_volume(DATADIR)
|
||||
EXEDIR = common.normalize_volume(EXEDIR)
|
||||
end
|
||||
|
||||
do
|
||||
|
@ -673,7 +688,7 @@ function core.init()
|
|||
-- We assume we have just a single project directory here. Now that StatusView
|
||||
-- is there show max files warning if needed.
|
||||
if core.project_directories[1].files_limit then
|
||||
show_max_files_warning()
|
||||
show_max_files_warning(core.project_directories[1])
|
||||
end
|
||||
|
||||
for _, filename in ipairs(files) do
|
||||
|
|
|
@ -412,7 +412,7 @@ end
|
|||
-- 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 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[y] = self.position[y]
|
||||
self.a.size[x] = n - ds
|
||||
|
@ -675,6 +675,10 @@ end
|
|||
|
||||
|
||||
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 it is not locked we don't accept the
|
||||
-- resize operation here because for proportional panes the resize is
|
||||
|
|
Loading…
Reference in New Issue