AwesomeFiles/config/awesome/helpers/filesystem.lua
2022-07-11 20:06:55 -05:00

426 lines
15 KiB
Lua
Executable file

local lgi = require("lgi")
local Gio = lgi.Gio
local Glib = lgi.GLib
local awful = require("awful")
local gtimer = require("gears.timer")
local tonumber = tonumber
local tostring = tostring
local ipairs = ipairs
local math = math
local os = os
local capi = { awesome = awesome }
local _filesystem = {}
function _filesystem.is_directory_readable_block(path)
local gfile = Gio.File.new_for_path(path)
local gfileinfo = gfile:query_info(
"standard::type,access::can-read,time::modified",
Gio.FileQueryInfoFlags.NONE
)
return gfileinfo and gfileinfo:get_file_type() == "DIRECTORY" and
gfileinfo:get_attribute_boolean("access::can-read")
end
function _filesystem.is_file_readable_block(path)
local gfile = Gio.File.new_for_path(path)
local gfileinfo = gfile:query_info(
"standard::type,access::can-read,time::modified",
Gio.FileQueryInfoFlags.NONE
)
return gfileinfo and gfileinfo:get_file_type() ~= "DIRECTORY" and
gfileinfo:get_attribute_boolean("access::can-read")
end
function _filesystem.read_file_block(path)
if _filesystem.is_file_readable_block(path) == false then
print("file '" .. path .. "' is not found or not readable...")
return nil
else
local gfile = Gio.File.new_for_path(path)
local content = gfile:load_contents()
if content == nil or content == false then
print("Failed reading " .. path)
return nil
else
return content
end
end
end
function _filesystem.query_info(path, callback)
local gfile = Gio.File.new_for_path(path)
gfile:query_info_async(
"standard::type,access::can-read,time::modified",
Gio.FileQueryInfoFlags.NONE, Glib.PRIORITY_DEFAULT,
nil,
function(_, info_result)
local info, error = gfile:query_info_finish(info_result)
if info == nil or error ~= nil then
callback(nil)
print(error)
return
else
callback(info)
end
end, nil)
end
function _filesystem.is_directory_readable(path, callback)
_filesystem.query_info(path, function(info)
if info ~= nil then
if info:get_file_type() == "DIRECTORY" and
info:get_attribute_boolean("access::can-read")
then
callback(true)
else
print("directory '" .. path .. "' is not found or not readable...")
callback(false)
end
else
print("info for directory '" .. path .. "' could not be retrived")
callback(false)
end
end)
end
function _filesystem.is_file_readable(path, callback)
_filesystem.query_info(path, function(info)
if info ~= nil then
if info:get_file_type() ~= "DIRECTORY" and
info:get_attribute_boolean("access::can-read")
then
callback(true)
else
print("file '" .. path .. "' is not found or not readable...")
callback(false)
end
else
print("info for file '" .. path .. "' could not be retrived")
callback(false)
end
end)
end
function _filesystem.make_directory(path, callback)
local gfile = Gio.File.new_for_path(path)
_filesystem.is_directory_readable(path, function(is_readable)
if is_readable then
print("directory '" .. path .. "' already exists")
callback(true)
return
else
gfile:make_directory_async(Glib.PRIORITY_DEFAULT, nil, function(file, task, c)
local result, error = gfile:make_directory_finish(task)
if result == false or error ~= nil then
print("Failed creating " .. path)
callback(false)
else
print("Successfully created " .. path)
callback(true)
end
end)
end
end)
end
function _filesystem.save_file(path, text, callback, is_retry)
print("writing to file " .. path)
local gfile = Gio.File.new_for_path(path)
_filesystem.is_file_readable(path, function(is_readable)
if not is_readable then
if is_retry then
print("failed creating file "..path)
if callback then
callback(false)
end
return
end
print("making parent directories...")
gfile:get_parent():make_directory_with_parents()
gfile:create_readwrite_async(Gio.FileCreateFlags.NONE, Glib.PRIORITY_DEFAULT, nil, function(_, create_result)
print("file created " .. tostring(gfile:create_readwrite_finish(create_result)))
_filesystem.save_file(path, text, callback, true)
end, nil)
else
gfile:open_readwrite_async(Glib.PRIORITY_DEFAULT, nil, function(_, io_stream_result)
local io_stream = gfile:open_readwrite_finish(io_stream_result)
io_stream:seek(0, Glib.SeekType.SET, nil)
local file = io_stream:get_output_stream()
file:write_all_async(text, Glib.PRIORITY_DEFAULT, nil, function(_, write_result)
local length_written = file:write_all_finish(write_result)
print("file written " .. length_written)
file:truncate(length_written, nil)
file:close_async(Glib.PRIORITY_DEFAULT, nil, function(_, file_close_result)
print("output stream closed " .. tostring(file:close_finish(file_close_result)))
io_stream:close_async(Glib.PRIORITY_DEFAULT, nil, function(_, stream_close_result)
print("file stream closed " .. tostring(io_stream:close_finish(stream_close_result)))
if callback then
callback(true)
end
end, nil)
end, nil)
end, nil)
end, nil)
end
end)
end
function _filesystem.read_file(path, callback)
local gfile = Gio.File.new_for_path(path)
_filesystem.is_file_readable(path, function(is_readable)
if not is_readable then
print("file '" .. path .. "' is not found or not readable...")
callback(nil)
else
gfile:load_contents_async(nil, function(file, task, c)
local content = gfile:load_contents_finish(task)
if content == nil then
print("Failed reading " .. path)
callback(nil)
else
callback(content)
end
end)
end
end)
end
function _filesystem.read_file_uri(uri, callback)
local gfile = Gio.File.new_for_uri(uri)
gfile:load_contents_async(nil, function(file, task, c)
local content = gfile:load_contents_finish(task)
if content == nil then
print("Failed reading " .. uri)
callback(nil)
else
callback(content)
end
end)
end
function _filesystem.delete_file(path, callback)
local gfile = Gio.File.new_for_path(path)
gfile:delete_async(Glib.PRIORITY_DEFAULT, nil, function(file, task, c)
local result, error = gfile:delete_finish(task)
if result == false or error ~= nil then
print("Failed deleting " .. tostring(error))
if callback then
callback(false)
end
else
if callback then
callback(true)
end
end
end)
end
function _filesystem.scan(path, callback, recursive)
if not path then
return
end
local result = {}
local function enumerator(path)
local gfile = Gio.File.new_for_path(path)
gfile:enumerate_children_async(
"standard::name,standard::type,access::can-read",
Gio.FileQueryInfoFlags.NONE,
0,
nil,
function(file, task, c)
local enum, error = file:enumerate_children_finish(task)
if enum == nil or error ~= nil then
print("Failed enumrating " .. path .. " " .. tostring(error))
callback(nil)
return
end
enum:next_files_async(99999, 0, nil, function(file_enum, task2, c)
local files, error = file_enum:next_files_finish(task2)
if files == nil or error ~= nil then
print("Failed enumrating " .. tostring(error))
callback(nil)
return
end
for _, file in ipairs(files) do
local file_child = enum:get_child(file)
local file_type = file:get_file_type()
local readable = file:get_attribute_boolean("access::can-read")
if file_type == "REGULAR" and readable then
local path = file_child:get_path()
if path ~= nil then
table.insert(result, path)
end
elseif file_type == "DIRECTORY" and recursive then
enumerator(file_child:get_path())
end
end
enum:close_async(0, nil)
callback(result)
end)
end)
end
enumerator(path)
end
function _filesystem.scan_with_folders(path, callback)
if not path then
return
end
local files_table = {}
local folders_table = {}
local function enumerator(path)
local gfile = Gio.File.new_for_path(path)
gfile:enumerate_children_async(
"standard::name,standard::type,access::can-read",
Gio.FileQueryInfoFlags.NONE,
0,
nil,
function(file, task, c)
local enum, error = file:enumerate_children_finish(task)
if enum == nil or error ~= nil then
print("Failed enumrating " .. path .. " " .. tostring(error))
callback(nil)
return
end
enum:next_files_async(99999, 0, nil, function(file_enum, task2, c)
local files, error = file_enum:next_files_finish(task2)
if files == nil or error ~= nil then
print("Failed enumrating " .. tostring(error))
callback(nil)
return
end
for _, file in ipairs(files) do
local file_child = enum:get_child(file)
local file_type = file:get_file_type()
local readable = file:get_attribute_boolean("access::can-read")
if file_type == "REGULAR" and readable then
local path = file_child:get_path()
if path ~= nil then
table.insert(files_table, path)
end
elseif file_type == "DIRECTORY" then
table.insert(folders_table, file_child:get_path())
end
end
enum:close_async(0, nil)
callback(files_table, folders_table)
end)
end)
end
enumerator(path)
end
function _filesystem.save_uri(path, uri, callback)
_filesystem.read_file_uri(uri, function(content)
if content == nil then
print("Failed to download file " .. uri)
callback(false)
else
_filesystem.save_file(path, content, function(result)
if result == true then
callback(true)
else
print("Failed to save " .. uri .. " to" .. path)
callback(false)
end
end)
end
end)
end
function _filesystem.remote_watch(path, uri, interval, callback, old_content_callback)
local function download()
_filesystem.read_file_uri(uri, function(content)
callback(content)
if content ~= nil and content ~= false then
_filesystem.read_file(path, function(old_content)
if old_content ~= nil and old_content ~= false then
if old_content_callback ~= nil then
old_content_callback(old_content)
end
end
_filesystem.save_file(path, content)
end)
end
end)
end
_filesystem.read_file(path, function(old_content)
if old_content ~= nil and old_content ~= false then
if old_content_callback ~= nil then
old_content_callback(old_content)
end
end
local timer
timer = gtimer
{
timeout = interval,
call_now = true,
autostart = true,
single_shot = false,
callback = function()
_filesystem.query_info(path, function(info)
if info ~= nil then
local time = info:get_modification_date_time()
local diff = math.ceil(Glib.DateTime.new_now_local():difference(time) / 1000000)
if diff >= interval then
print("Enough time has passed, redownloading " .. path)
download()
else
_filesystem.read_file(path, function(content)
if content == nil or content:gsub("%s+", "") == "" then
print("Empty file, Redownloading " .. path)
download()
else
callback(content)
end
end)
-- Schedule an update for when the remaining time to complete the interval passes
timer:stop()
gtimer.start_new(interval - diff, function()
print("Finally! redownloading " .. path)
download()
timer:again()
end)
end
else
print(path .. " doesn't exist, downloading " .. uri)
download()
end
end)
end
}
end)
end
function _filesystem.get_awesome_config_dir(sub_folder)
return (capi.awesome.conffile:match(".*/") or "./") .. sub_folder .. "/"
end
function _filesystem.get_cache_dir(sub_folder)
return (os.getenv("XDG_CACHE_HOME") or os.getenv("HOME") .. "/.cache")
.. "/awesome/" .. sub_folder .. "/"
end
function _filesystem.get_xdg_cache_home(sub_folder)
return (os.getenv("XDG_CACHE_HOME") or os.getenv("HOME") .. "/.cache")
.. "/" .. sub_folder .. "/"
end
return _filesystem