mirror of
https://github.com/wez/wezterm.git
synced 2024-10-04 02:08:07 +03:00
Improved read_dir and added documentation.
This commit is contained in:
parent
d4c75b3d6d
commit
6cb3ca9bb4
@ -4,7 +4,7 @@ tags:
|
||||
- utility
|
||||
- filesystem
|
||||
---
|
||||
# `wezterm.read_dir(path)`
|
||||
# `wezterm.read_dir(path [, callback])`
|
||||
|
||||
{{since('20200503-171512-b13ef15f')}}
|
||||
|
||||
@ -22,4 +22,121 @@ for _, v in ipairs(wezterm.read_dir '/etc') do
|
||||
end
|
||||
```
|
||||
|
||||
{{since('nightly')}}
|
||||
|
||||
`read_dir` accepts an optional callback function that can be used on each entry
|
||||
of the directory being read with `read_dir`. The callback function should be of the form
|
||||
```
|
||||
function(filepath, meta)
|
||||
-- do things with the filepath and meta
|
||||
end
|
||||
```
|
||||
where `filepath` is a Lua string of the entry's path and meta is a special `MetaData`
|
||||
object for the entry.
|
||||
|
||||
If you want to use the function to change the output of read_dir, you should make sure
|
||||
to return values in one of the two following forms:
|
||||
```
|
||||
bool,
|
||||
{ bool, integer },
|
||||
{ bool, integer, integer },
|
||||
{ bool, integer, integer, integer },
|
||||
and so on...
|
||||
```
|
||||
|
||||
If the function returns `true`, then the given `filepath` will be included in the output
|
||||
of `read_dir`, and if the function returns `false`, then the given `filepath` will be
|
||||
excluded from the output.
|
||||
|
||||
If you return an array `{ bool, integer... }`, then the boolean will have the same meaning
|
||||
as above, and the integers will be used for sorting (in the given order). (See below.)
|
||||
|
||||
If the function returns anything other than boolean or an array starting with a boolean,
|
||||
or if we don't include the optional function at all, then the default behavior is to include
|
||||
all `filepath`s.
|
||||
|
||||
The `MetaData` object (and thus`meta`) contains information about the entry (either
|
||||
a directory, a file or a symlink), which can be accessed with the following methods:
|
||||
|
||||
* `is_dir` - returns true if the entry is a directory and false otherwise
|
||||
* `is_file` - returns true if the entry is a file and false otherwise
|
||||
* `is_symlink` - returns true if the entry is symlink and false otherwise
|
||||
* `is_readonly` - returns true if the entry is readonly and false otherwise
|
||||
* `secs_since_modified` - returns an integer with the number of seconds since
|
||||
the entry was last modified
|
||||
* `secs_since_accessed` - returns an integer with the number of seconds since
|
||||
the entry was last accessed
|
||||
* `secs_since_created` - returns an integer with the number of seconds since
|
||||
the entry was created
|
||||
* `bytes` - returns the size of the entry in bytes
|
||||
|
||||
### Examples
|
||||
|
||||
If we want `read_only` to return the name (not path) of all folders and symlinks that
|
||||
are not hidden files or folders (i.e., not starting with a `.`) in the home directory,
|
||||
and then sort them first by the time since we last accessed the entry and thereafter
|
||||
by the length of the filepath, we can do the following:
|
||||
|
||||
```lua
|
||||
string.startswith = function(str, start)
|
||||
return str:sub(1, #start) == start
|
||||
end
|
||||
|
||||
string.basename = function(s)
|
||||
return string.gsub(s, '(.*[/\\])(.*)', '%2')
|
||||
end
|
||||
|
||||
local wezterm = require 'wezterm'
|
||||
local home = wezterm.home_dir
|
||||
|
||||
for _, v in
|
||||
ipairs(wezterm.read_dir(home, function(filepath, meta)
|
||||
return {
|
||||
(meta:is_symlink() or meta:is_dir())
|
||||
and (not filepath:basename():startswith '.'),
|
||||
meta:secs_since_accessed(),
|
||||
#filepath,
|
||||
}
|
||||
end))
|
||||
do
|
||||
wezterm.log_info('entry: ' .. v:basename())
|
||||
end
|
||||
```
|
||||
|
||||
Note: The purpose of sorting multiple times is that each sort don't swap equal values,
|
||||
so if we for example have a lot of entries with the same length filepath, then we can
|
||||
make sure that entries of each length are additionally sorted by when they were last
|
||||
accessed.
|
||||
|
||||
If we want a list of the path of all files of size at least 1kB and a most 10MB
|
||||
that we created less than a year ago, and that is sorted from oldest to newest by creation
|
||||
time, we can do the following:
|
||||
|
||||
```lua
|
||||
local wezterm = require 'wezterm'
|
||||
local home = wezterm.home_dir
|
||||
|
||||
local year_in_secs = 60 * 60 * 24 * 365
|
||||
|
||||
local tbl = wezterm.read_dir(home, function(filepath, meta)
|
||||
return {
|
||||
meta:is_file()
|
||||
and (10 ^ 3 < meta:bytes() and meta:bytes() < 10 ^ 7)
|
||||
and (meta:secs_since_created() < year_in_secs),
|
||||
-meta:secs_since_created(), -- we do minus to reverse the order
|
||||
}
|
||||
end)
|
||||
wezterm.log_info(tbl)
|
||||
```
|
||||
|
||||
If we just want to list all directories in the home directory, we can do the following:
|
||||
```lua
|
||||
local wezterm = require 'wezterm'
|
||||
local home = wezterm.home_dir
|
||||
|
||||
local tbl = wezterm.read_dir(home, function(filepath, meta)
|
||||
return meta:is_dir()
|
||||
end)
|
||||
wezterm.log_info(tbl)
|
||||
```
|
||||
|
||||
|
@ -78,7 +78,9 @@ async fn read_dir<'lua>(
|
||||
let mut dir = smol::fs::read_dir(path)
|
||||
.await
|
||||
.map_err(mlua::Error::external)?;
|
||||
let mut entries = vec![];
|
||||
let mut entries: Vec<String> = vec![];
|
||||
let mut sort = false; // assume we are not sorting
|
||||
let mut sort_by_vec: Vec<Vec<i64>> = vec![];
|
||||
while let Some(entry) = dir.next().await {
|
||||
let entry = entry.map_err(mlua::Error::external)?;
|
||||
if let Some(utf8) = entry.path().to_str() {
|
||||
@ -86,21 +88,40 @@ async fn read_dir<'lua>(
|
||||
|
||||
// default behavior is include everything in the directory
|
||||
let mut include_entry = true;
|
||||
let mut sort_by: Vec<i64> = vec![];
|
||||
if let Some(func) = &function {
|
||||
include_entry = match func.call((utf8.to_string(), MetaData(meta))) {
|
||||
Ok(mlua::Value::Boolean(b)) => b,
|
||||
match func.call((utf8.to_string(), MetaData(meta))) {
|
||||
Ok(mlua::Value::Boolean(b)) => {
|
||||
include_entry = b;
|
||||
}
|
||||
Ok(mlua::Value::Table(tbl)) => {
|
||||
let mut iter = tbl.sequence_values();
|
||||
match iter.next() {
|
||||
Some(Ok(mlua::Value::Boolean(b))) => {
|
||||
include_entry = b;
|
||||
}
|
||||
_ => (),
|
||||
};
|
||||
while let Some(Ok(mlua::Value::Integer(i))) = iter.next() {
|
||||
sort = true;
|
||||
sort_by.push(i)
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
return Err(mlua::Error::external(format!(
|
||||
"the optional read_dir function returns the error: {}",
|
||||
err
|
||||
)));
|
||||
}
|
||||
_ => true,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
if include_entry {
|
||||
entries.push(utf8.to_string());
|
||||
if sort {
|
||||
sort_by_vec.push(sort_by);
|
||||
}
|
||||
} // if include_entry is false, don't add entry to entries
|
||||
} else {
|
||||
return Err(mlua::Error::external(anyhow!(
|
||||
@ -109,7 +130,30 @@ async fn read_dir<'lua>(
|
||||
)));
|
||||
}
|
||||
}
|
||||
Ok(entries)
|
||||
|
||||
if sort {
|
||||
let mut sorted: Vec<String> = entries.clone();
|
||||
for i in 0..sort_by_vec[0].len() {
|
||||
let sort_by_ivec: Vec<i64> = sort_by_vec.iter().map(|v| v[i]).collect();
|
||||
|
||||
let mut zipped: Vec<(String, i64)> = entries
|
||||
.clone()
|
||||
.into_iter()
|
||||
.zip(sort_by_ivec.into_iter())
|
||||
.collect();
|
||||
zipped.sort_by_key(|pair| pair.1);
|
||||
|
||||
sorted = zipped
|
||||
.iter()
|
||||
.map(|pair| pair.0.clone())
|
||||
.map(|s| s.to_string())
|
||||
.collect();
|
||||
}
|
||||
|
||||
Ok(sorted)
|
||||
} else {
|
||||
Ok(entries)
|
||||
}
|
||||
}
|
||||
|
||||
async fn glob<'lua>(
|
||||
|
Loading…
Reference in New Issue
Block a user