neyuki 0.5.0

A small Lua-like scripting language implemented in Rust
# @neyuki/fs

Files, directories and paths. Text files are read and written as UTF-8 strings.

```lua
local fs = require("@neyuki/fs")

fs.write("notes.txt", "first line\n")
fs.append("notes.txt", "second line\n")
for line in fs.lines("notes.txt") do print(line) end

for _, path in fs.walk("src") do
    if fs.extension(path) == ".nyk" then print(path, fs.info(fs.join("src", path)).size) end
end
```

## fs.read(path: string): string

The contents of a text file.

## fs.write(path: string, text: string): ()

Replaces the contents of a file, creating it if needed.

## fs.append(path: string, text: string): ()

Adds text to the end of a file, creating it if needed.

## fs.lines(path: string): () -> string?

An iterator over the lines of a file, without their `\n` or `\r\n` endings.

## fs.open(path: string, mode: string?): File

Opens a file as a `File` object. `mode` is `"r"` (read, the default; the file must exist), `"w"` (write, replacing the contents) or `"a"` (append). A `File` has the fields `path` and `mode` and these methods:

- `file:read()` returns the whole contents.
- `file:write(text, append?)` writes text. The first write to a `"w"` file replaces the contents and later ones append; `"a"` files always append.
- `file:lines()` returns an iterator over the lines.
- `file:close()` closes it; any later call raises an error.

## fs.exists(path: string): boolean

Whether a file or directory exists at `path`.

## fs.isFile(path: string): boolean

Whether `path` is a file.

## fs.isDir(path: string): boolean

Whether `path` is a directory.

## fs.info(path: string): table?

`{ size, isDir, isFile, readonly, modified, created }` for a path, or `nil` when nothing is there. `size` is in bytes and the times are seconds since the Unix epoch, ready for `os.date`.

```lua
local info = fs.info("notes.txt")
print(info.size, os.date("%Y-%m-%d %H:%M", info.modified))
```

## fs.copy(from: string, to: string): number

Copies a file, replacing `to`, and returns the number of bytes copied.

## fs.rename(from: string, to: string): ()

Moves or renames a file or directory.

## fs.remove(path: string, recursive: boolean?): ()

Deletes a file or an empty directory. With `recursive`, deletes a directory and everything in it.

## fs.mkdir(path: string, recursive: boolean?): ()

Creates a directory. With `recursive`, also creates missing parents and does nothing if it already exists.

## fs.list(path: string): {string}

The names of the entries in a directory, sorted.

## fs.walk(path: string): {string}

Every file under a directory, at any depth, as paths relative to it joined with `/`, sorted. Directories themselves are not listed.

## fs.join(...: string): string

Joins path parts with `/` (which every platform accepts) without doubling separators. A part that is an absolute path starts over.

```lua
print(fs.join("assets", "img/", "logo.png")) --> assets/img/logo.png
```

## fs.basename(path: string): string

The last part of a path: `"guide.md"` for `"docs/guide.md"`.

## fs.dirname(path: string): string

Everything before the last part: `"docs"` for `"docs/guide.md"`, and `"."` for a bare name.

## fs.extension(path: string): string

The extension of the last part including the dot (`".md"`), or `""` when there is none. A leading dot as in `".gitignore"` is not an extension.

## fs.absolute(path: string): string

`path` made absolute against the working directory, without resolving links.

## fs.cwd(): string

The working directory, which relative paths start from.