Skip to content

Commit

Permalink
wip readme
Browse files Browse the repository at this point in the history
Signed-off-by: Tony Worm <tony@hofstadter.io>
  • Loading branch information
verdverm committed Oct 11, 2021
1 parent dc37150 commit 19e2cec
Showing 1 changed file with 132 additions and 58 deletions.
190 changes: 132 additions & 58 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,86 +1,69 @@
# cuetils
# Cuetils

CUE utilities and helpers for various tasks.
CUE utilities and helpers
for working with tree based objects
in any combination of CUE, Yaml, and JSON.

## Using

### As a library

Add to your project with `hof mod` or another method.

https://cuetorials.com/first-steps/modules-and-packages/#dependency-management

### As a binary

Download a [release from GitHub](https://github.com/hofstadter-io/cuetils/releases).
The `cuetils` program is useful for bulk operations
or when you don't want to write extra CUE or Go.

__Structural:__
Download a [release from GitHub](https://github.com/hofstadter-io/cuetils/releases).

```
st -h
cuetils -h
```

## Helpers
### As a Go library

Many of these make use of the
["function" pattern](https://cuetorials.com/patterns/functions/).

### RecurseN
The Go libraries are optimized and have more capabilities.

A function factory for bounded recursion, defaulting to 20.
This is a pattern to get around CUE's cycle detection
by creating a struct with fields named for each iteration.
See https://cuetorials.com/deep-dives/recursion/ for more details.
```shell
go get github.com/hofstadter-io/cuetils@latest
```

```cue
#RecurseN: {
#maxiter: uint | *20
#funcFactory: {
#next: _
#func: _
}
```
import "github.com/hofstadter-io/cuetils/structural"
```

for k, v in list.Range(0, #maxiter, 1) {
#funcs: "\(k)": (#funcFactory & {#next: #funcs["\(k+1)"]}).#func
}
#funcs: "\(#maxiter)": null
### As a CUE library

#funcs["0"]
}
```
The CUE libraries all use the [RecurseN](#recursen) helper
and make use of the ["function" pattern](https://cuetorials.com/patterns/functions/).
You can also write [custom operators](#custom-operators).

The core of the bounded recursion is this structural comprehension (unrolled for loop).
The "recursive call" is made with the following pattern.
Add to your project with `hof mod` or another method.
See: https://cuetorials.com/first-steps/modules-and-packages/#dependency-management

```cue
(#funcFactory & {#next: #funcs["\(k+1)"]}).#func
```
import "github.com/hofstadter-io/cuetils/structural"
```

You can override the iterations with `{ #maxdepth: 100 }` at the point of
usage or by creating new helpers from the existing ones.
You may need to adjust this

- up for deep objects
- down if runtime is an issue

```cue
import "github.com/hofstadter-io/cuetils/structural"
## Structural Helpers

#LeaguesDeep: structural.#Depth & { #maxdepth: 10000 }
```

- [Count](#count) the nodes in an object
- [Depth](#depth) how deep an object is
- [Diff](#diff) two objects, producing a structured diff
- [Patch](#patch) an object, producing a new object
- [Pick](#pick) a subojbect from another, selecting only the parts you want
- [Maks](#mask) a subobject from another, filtering out parts you don't want
- [Replace](#replace) with a subobject, updating fields found
- [Upsert](#upsert) with a subobject, updating and adding fields
- [Transform](#transform) one or more objects into another using CUE
- [Validate](#validate) one or more objects with the power of CUE

### Structural

The following examples use
Some notes:

```cue
import (
st "github.com/hofstadter-io/cuetils/structural"
)
```

They work by checking of the two operands unify.
The helpers work by checking if two operands unify.
We try to make note of the edge cases, which also
depends on if you are using CUE, Go, or `cuetils`.

- for __diff__ and __patch__, `int & 1` like expressions will _not_ be detected
- for __pick__ and __mask__, `int & 1` like expression are detected
Expand All @@ -90,7 +73,33 @@ It may be workable if the list sizes are known and order consistent.
[Associative Lists](https://cuetorials.com/cueology/futurology/associative-lists/)
may solve this issue. We don't currently have good syntax for specifying the key to match elements on.

__#Depth__ calculates the depth of an object

### Count

__#Count__ calculates how many nodes are in an object.

### Depth

<details open>
<summary>`cuetils` example</summary>
<br>
```cue
tree: {
a: {
foo: "bar"
a: b: c: "d"
}
cow: "moo"
}
```

```shell
$ cuetils depth tree.cue
5
```
</details>

__#Depth__ calculates the deepest branch of an object.

```cue
tree: {
Expand All @@ -105,6 +114,8 @@ depth: (st.#Depth & { #in: tree }).out
depth: 5
```

### Diff

__#Diff__ computes a semantic diff object

```cue
Expand Down Expand Up @@ -153,6 +164,9 @@ diff: {
}
```


### Patch

__#Patch__ applies a diff object

```cue
Expand Down Expand Up @@ -201,6 +215,8 @@ patch: {
}
```

### Pick

__#Pick__ extracts a subobject

```cue
Expand Down Expand Up @@ -233,6 +249,8 @@ pick: {
}
```

### Mask

__#Mask__ removes a subobject

```cue
Expand Down Expand Up @@ -265,7 +283,63 @@ mask: {
}
```

### Custom Recursion

### Replace

### Upsert

### Transform

### Validate



### RecurseN

A function factory for bounded recursion, defaulting to 20.
This is a pattern to get around CUE's cycle detection
by creating a struct with fields named for each iteration.
See https://cuetorials.com/deep-dives/recursion/ for more details.

```cue
#RecurseN: {
#maxiter: uint | *20
#funcFactory: {
#next: _
#func: _
}
for k, v in list.Range(0, #maxiter, 1) {
#funcs: "\(k)": (#funcFactory & {#next: #funcs["\(k+1)"]}).#func
}
#funcs: "\(#maxiter)": null
#funcs["0"]
}
```

The core of the bounded recursion is this structural comprehension (unrolled for loop).
The "recursive call" is made with the following pattern.

```cue
(#funcFactory & {#next: #funcs["\(k+1)"]}).#func
```

You can override the iterations with `{ #maxdepth: 100 }` at the point of
usage or by creating new helpers from the existing ones.
You may need to adjust this

- up for deep objects
- down if runtime is an issue

```cue
import "github.com/hofstadter-io/cuetils/structural"
#LeaguesDeep: structural.#Depth & { #maxdepth: 10000 }
```


### Custom Helpers

You can make new helpers by building on the `#RecurseN` pattern.
You need two definitions, a factory and the user facing, recursed version.
Expand Down

0 comments on commit 19e2cec

Please sign in to comment.