Skip to content

Commit

Permalink
Added readme and canonical_path + fixed dirname.
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Kongsgaard authored and Daniel Kongsgaard committed Sep 23, 2023
1 parent 0870727 commit 47ab375
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 18 deletions.
30 changes: 30 additions & 0 deletions docs/config/lua/wezterm/basename.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
title: wezterm.basename
tags:
- utility
- filesystem
---
# `wezterm.basename(path)`

{{since('nightly')}}

This function returns a string containing the basename of the given path.
The function does not check whether the given path actually exists.
Due to limitations in the lua bindings, all of the paths
must be able to be represented as UTF-8 or this function will generate an
error.

Note: This function is similar to the shell command basename, but it behaves
slightly different in some edge case. E.g. `wezterm.basename 'foo.txt/.//'`
returns `'foo.txt` since trailing `/`s are ignored and so is one `.`.
But `wezterm.basename 'foo.txt/..'` returns `'..'`. This behaviour comes
from Rust's [`std::path::PathBuf`](https://doc.rust-lang.org/nightly/std/path/struct.PathBuf.html#method.file_name).

```lua
local wezterm = require 'wezterm'
local basename = wezterm.basename

wezterm.log_info( 'baz.txt = ' .. basename '/foo/bar/baz.txt' )
```

See also [dirname](dirname.md).
37 changes: 37 additions & 0 deletions docs/config/lua/wezterm/canonical_path.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
title: wezterm.canonical_path
tags:
- utility
- filesystem
---
# `wezterm.canonical_path(path)`

{{since('nightly')}}

This function returns a string with the canonical form of a path if it exists.
The returned path is in absolute form with all intermediate components normalized
and symbolic links resolved.
Due to limitations in the lua bindings, all of the paths
must be able to be represented as UTF-8 or this function will generate an
error.

The function can for example be used get the correct absolute path for a path
in a different format.
```lua
local wezterm = require 'wezterm'
local canonical_path = wezterm.canonical_path

wezterm.log_error( wezterm.home_dir .. ' = ' canonical_path( wezterm.home_dir .. "/.") )
```

Another common use case is to find the absolute path of a symlink. E.g., Dropbox is usually
symlinked to `$HOME/Dropbox` on macOS, but is located at `$HOME/Library/CloudStorage/Dropbox`.
```lua
local wezterm = require 'wezterm'
local canonical_path = wezterm.canonical_path
local home_dir = wezterm.home_dir

wezterm.log_error( home_dir .. '/Library/CloudStorage/Dropbox' .. ' = ' .. canonical_path( home_dir .. "/Dropbox") )
```

See also [glob](glob.md).
37 changes: 37 additions & 0 deletions docs/config/lua/wezterm/dirname.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
title: wezterm.dirname
tags:
- utility
- filesystem
---
# `wezterm.dirname(path)`

{{since('nightly')}}

This function returns a string containing the dirname of the given path.
The function does not check whether the given path actually exists.
Due to limitations in the lua bindings, all of the paths
must be able to be represented as UTF-8 or this function will generate an
error.

Note: This function is similar to the shell command dirname, but it might
behave slightly different in some edge case.

```lua
local wezterm = require 'wezterm'
local dirname = wezterm.dirname

wezterm.log_error( '/foo/bar = ' .. dirname '/foo/bar/baz.txt' )
```

If you want only the directory name and not the full path, you can use
`basename` and `dirname` together. E.g.:
```lua
local wezterm = require 'wezterm'
local basename = wezterm.basename
local dirname = wezterm.dirname

wezterm.log_error( 'bar = ' .. basename(dirname '/foo/bar/baz.txt') )
```

See also [basename](basename.md).
47 changes: 29 additions & 18 deletions lua-api-crates/filesystem/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub fn register(lua: &Lua) -> anyhow::Result<()> {
wezterm_mod.set("read_dir", lua.create_async_function(read_dir)?)?;
wezterm_mod.set("basename", lua.create_async_function(basename)?)?;
wezterm_mod.set("dirname", lua.create_async_function(dirname)?)?;
wezterm_mod.set("canonical_path", lua.create_async_function(canonical_path)?)?;
wezterm_mod.set("glob", lua.create_async_function(glob)?)?;
Ok(())
}
Expand All @@ -32,15 +33,16 @@ async fn read_dir<'lua>(_: &'lua Lua, path: String) -> mlua::Result<Vec<String>>
Ok(entries)
}

// similar (but not equal) to the shell command basename
async fn basename<'lua>(_: &'lua Lua, path: String) -> mlua::Result<String> {
// to check if the path actually exists, we can use:
/* let dir = smol::fs::canonicalize(path)
/* let path = smol::fs::canonicalize(path)
.await
.map_err(mlua::Error::external)?; */
let path = Path::new(&path);
if let Some(os_str_basename) = path.file_name() {
if let Some(basename) = os_str_basename.to_str() {
Ok(basename.to_string())
if let Some(basename) = path.file_name() {
if let Some(utf8) = basename.to_str() {
Ok(utf8.to_string())
} else {
return Err(mlua::Error::external(anyhow!(
"path entry {} is not representable as utf8",
Expand All @@ -53,32 +55,41 @@ async fn basename<'lua>(_: &'lua Lua, path: String) -> mlua::Result<String> {
}
}

// return the path without its final component if there is one
// similar to the shell command dirname
async fn dirname<'lua>(_: &'lua Lua, path: String) -> mlua::Result<String> {
// to check if the path actually exists, we can use:
/* let dir = smol::fs::canonicalize(path)
.await
.map_err(mlua::Error::external)?; */
let path = Path::new(&path);
if let Some(parent_path) = path.parent() {
if let Some(os_str_parent) = parent_path.file_name() {
if let Some(dirname) = os_str_parent.to_str() {
Ok(dirname.to_string())
} else {
return Err(mlua::Error::external(anyhow!(
if let Some(utf8) = parent_path.to_str() {
Ok(utf8.to_string())
} else {
return Err(mlua::Error::external(anyhow!(
"path entry {} is not representable as utf8",
path.display()
)));
}
} else {
// file name returns None if parent_path ends in ..
Ok("..".to_string())
)));
}
} else {
// parent returns None if the path terminates in a root or prefix
Ok("".to_string())
}
}

// if path exists return the canonical form of the path with all
// intermediate components normalized and symbolic links resolved
async fn canonical_path<'lua>(_: &'lua Lua, path: String) -> mlua::Result<String> {
let path = smol::fs::canonicalize(&path)
.await
.map_err(mlua::Error::external)?;
if let Some(utf8) = &path.to_str() {
Ok(utf8.to_string())
} else {
return Err(mlua::Error::external(anyhow!(
"path entry {} is not representable as utf8",
path.display()
)));
}
}

async fn glob<'lua>(
_: &'lua Lua,
(pattern, path): (String, Option<String>),
Expand Down

0 comments on commit 47ab375

Please sign in to comment.