forked from awesomeWM/awesome
-
Notifications
You must be signed in to change notification settings - Fork 0
/
filesystem.lua
225 lines (195 loc) · 9.31 KB
/
filesystem.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
---------------------------------------------------------------------------
--- Various filesystem utility functions.
--
-- Note that these functions are blocking. If you need to do a large number of
-- I/O operations, it is better to use `lgi.Gio` async functions.
--
-- @utillib gears.filesystem
---------------------------------------------------------------------------
-- Grab environment we need
local Gio = require("lgi").Gio
local gstring = require("gears.string")
local gtable = require("gears.table")
local filesystem = {}
local function make_directory(gfile)
local success, err = gfile:make_directory_with_parents()
if success then
return true
end
if err.domain == Gio.IOErrorEnum and err.code == "EXISTS" then
-- Directory already exists, let this count as success
return true
end
return false, err
end
--- Create a directory, including all missing parent directories.
-- @tparam string dir The directory.
-- @return (true, nil) on success, (false, err) on failure
-- @staticfct gears.filesystem.make_directories
function filesystem.make_directories(dir)
return make_directory(Gio.File.new_for_path(dir))
end
function filesystem.mkdir(dir)
require("gears.debug").deprecate("gears.filesystem.make_directories", {deprecated_in=5})
return filesystem.make_directories(dir)
end
--- Create all parent directories for a given path.
-- @tparam string path The path whose parents should be created.
-- @return (true, nil) on success, (false, err) on failure.
-- @staticfct gears.filesystem.make_parent_directories
function filesystem.make_parent_directories(path)
return make_directory(Gio.File.new_for_path(path):get_parent())
end
--- Check if a file exists, is readable and not a directory.
-- @tparam string filename The file path.
-- @treturn boolean True if file exists and is readable.
-- @staticfct gears.filesystem.file_readable
function filesystem.file_readable(filename)
local gfile = Gio.File.new_for_path(filename)
local gfileinfo = gfile:query_info("standard::type,access::can-read",
Gio.FileQueryInfoFlags.NONE)
return gfileinfo and gfileinfo:get_file_type() ~= "DIRECTORY" and
gfileinfo:get_attribute_boolean("access::can-read")
end
--- Check if a file exists, is executable and not a directory.
-- @tparam string filename The file path.
-- @treturn boolean True if file exists and is executable.
-- @staticfct gears.filesystem.file_executable
function filesystem.file_executable(filename)
local gfile = Gio.File.new_for_path(filename)
local gfileinfo = gfile:query_info("standard::type,access::can-execute",
Gio.FileQueryInfoFlags.NONE)
return gfileinfo and gfileinfo:get_file_type() ~= "DIRECTORY" and
gfileinfo:get_attribute_boolean("access::can-execute")
end
--- Check if a path exists, is readable and a directory.
-- @tparam string path The directory path.
-- @treturn boolean True if path exists and is readable.
-- @staticfct gears.filesystem.dir_readable
function filesystem.dir_readable(path)
local gfile = Gio.File.new_for_path(path)
local gfileinfo = gfile:query_info("standard::type,access::can-read",
Gio.FileQueryInfoFlags.NONE)
return gfileinfo and gfileinfo:get_file_type() == "DIRECTORY" and
gfileinfo:get_attribute_boolean("access::can-read")
end
--- Check if a path exists, is writable and a directory.
-- @tparam string path The directory path.
-- @treturn boolean True if path exists and is writable.
-- @staticfct gears.filesystem.dir_writable
function filesystem.dir_writable(path)
local gfile = Gio.File.new_for_path(path)
local gfileinfo = gfile:query_info("standard::type,access::can-write",
Gio.FileQueryInfoFlags.NONE)
return gfileinfo and gfileinfo:get_file_type() == "DIRECTORY" and
gfileinfo:get_attribute_boolean("access::can-write")
end
--- Check if a path is a directory.
-- @tparam string path The directory path
-- @treturn boolean True if path exists and is a directory.
-- @staticfct gears.filesystem.is_dir
function filesystem.is_dir(path)
return Gio.File.new_for_path(path):query_file_type({}) == "DIRECTORY"
end
--- Get the config home according to the XDG basedir specification.
-- @return the config home (XDG_CONFIG_HOME) with a slash at the end.
-- @staticfct gears.filesystem.get_xdg_config_home
function filesystem.get_xdg_config_home()
return (os.getenv("XDG_CONFIG_HOME") or os.getenv("HOME") .. "/.config") .. "/"
end
--- Get the cache home according to the XDG basedir specification.
-- @return the cache home (XDG_CACHE_HOME) with a slash at the end.
-- @staticfct gears.filesystem.get_xdg_cache_home
function filesystem.get_xdg_cache_home()
return (os.getenv("XDG_CACHE_HOME") or os.getenv("HOME") .. "/.cache") .. "/"
end
--- Get the data home according to the XDG basedir specification.
-- @treturn string the data home (XDG_DATA_HOME) with a slash at the end.
-- @staticfct gears.filesystem.get_xdg_data_home
function filesystem.get_xdg_data_home()
return (os.getenv("XDG_DATA_HOME") or os.getenv("HOME") .. "/.local/share") .. "/"
end
--- Get the data dirs according to the XDG basedir specification.
-- @treturn table the data dirs (XDG_DATA_DIRS) with a slash at the end of each entry.
-- @staticfct gears.filesystem.get_xdg_data_dirs
function filesystem.get_xdg_data_dirs()
local xdg_data_dirs = os.getenv("XDG_DATA_DIRS") or "/usr/share:/usr/local/share"
return gtable.map(
function(dir) return dir .. "/" end,
gstring.split(xdg_data_dirs, ":"))
end
--- Get the path to the user's config dir.
-- This is the directory containing the configuration file ("rc.lua").
-- @return A string with the requested path with a slash at the end.
-- @staticfct gears.filesystem.get_configuration_dir
function filesystem.get_configuration_dir()
return awesome.conffile:match(".*/") or "./"
end
--- Get the path to a directory that should be used for caching data.
-- @return A string with the requested path with a slash at the end.
-- @staticfct gears.filesystem.get_cache_dir
function filesystem.get_cache_dir()
local result = filesystem.get_xdg_cache_home() .. "awesome/"
filesystem.make_directories(result)
return result
end
--- Get the path to the directory where themes are installed.
-- @return A string with the requested path with a slash at the end.
-- @staticfct gears.filesystem.get_themes_dir
function filesystem.get_themes_dir()
return (os.getenv('AWESOME_THEMES_PATH') or awesome.themes_path) .. "/"
end
--- Get the path to the directory where our icons are installed.
-- @return A string with the requested path with a slash at the end.
-- @staticfct gears.filesystem.get_awesome_icon_dir
function filesystem.get_awesome_icon_dir()
return (os.getenv('AWESOME_ICON_PATH') or awesome.icon_path) .. "/"
end
--- Get the user's config or cache dir.
-- It first checks XDG_CONFIG_HOME / XDG_CACHE_HOME, but then goes with the
-- default paths.
-- @param d The directory to get (either "config" or "cache").
-- @return A string containing the requested path.
-- @staticfct gears.filesystem.get_dir
function filesystem.get_dir(d)
if d == "config" then
-- No idea why this is what is returned, I recommend everyone to use
-- get_configuration_dir() instead
require("gears.debug").deprecate("gears.filesystem.get_xdg_config_home() .. 'awesome/'", {deprecated_in=5})
return filesystem.get_xdg_config_home() .. "awesome/"
elseif d == "cache" then
require("gears.debug").deprecate("gears.filesystem.get_cache_dir", {deprecated_in=5})
return filesystem.get_cache_dir()
end
end
--- Get the name of a random file from a given directory.
-- @tparam string path The directory to search.
-- @tparam[opt] table exts Specific extensions to limit the search to. eg:`{ "jpg", "png" }`
-- If ommited, all files are considered.
-- @tparam[opt=false] boolean absolute_path Return the absolute path instead of the filename.
-- @treturn string|nil A randomly selected filename from the specified path (with
-- a specified extension if required) or nil if no suitable file is found. If `absolute_path`
-- is set, then a path is returned instead of a file name.
-- @staticfct gears.filesystem.get_random_file_from_dir
function filesystem.get_random_file_from_dir(path, exts, absolute_path)
local files, valid_exts = {}, {}
-- Transforms { "jpg", ... } into { [jpg] = #, ... }
if exts then for i, j in ipairs(exts) do valid_exts[j:lower():gsub("^[.]", "")] = i end end
-- Build a table of files from the path with the required extensions
local file_list = Gio.File.new_for_path(path):enumerate_children("standard::*", 0)
-- This will happen when the directory doesn't exist.
if not file_list then return nil end
for file in function() return file_list:next_file() end do
if file:get_file_type() == "REGULAR" then
local file_name = file:get_display_name()
if not exts or valid_exts[file_name:lower():match(".+%.(.*)$") or ""] then
table.insert(files, file_name)
end
end
end
if #files == 0 then return nil end
-- Return a randomly selected filename from the file table
local file = files[math.random(#files)]
return absolute_path and (path:gsub("[/]*$", "") .. "/" .. file) or file
end
return filesystem