Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support descriptions from comments #70

Merged
merged 1 commit into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 35 additions & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,19 @@ fn collect_entries(root: rnix::Root, category: &str) -> Vec<ManualEntry> {
vec![]
}

fn retrieve_description(nix: &rnix::Root, description: &str, category: &str) -> String {
format!(
"# {} {{#sec-functions-library-{}}}\n{}\n",
description,
category,
&nix.syntax()
.first_child()
.and_then(|node| retrieve_doc_comment(&node, true))
.and_then(|comment| handle_indentation(&comment))
.unwrap_or_default()
)
}

fn main() {
let mut output = io::stdout();
let opts = Options::parse();
Expand All @@ -406,14 +419,10 @@ fn main() {
.expect("could not read location information"),
};
let nix = rnix::Root::parse(&src).ok().expect("failed to parse input");
let description = retrieve_description(&nix, &opts.description, &opts.category);

// TODO: move this to commonmark.rs
writeln!(
output,
"# {} {{#sec-functions-library-{}}}\n",
&opts.description, opts.category
)
.expect("Failed to write header");
writeln!(output, "{}", description).expect("Failed to write header");

for entry in collect_entries(nix, &opts.category) {
entry
Expand Down Expand Up @@ -450,6 +459,26 @@ fn test_main() {
insta::assert_snapshot!(output);
}

#[test]
fn test_description_of_lib_debug() {
let mut output = Vec::new();
let src = fs::read_to_string("test/lib-debug.nix").unwrap();
let nix = rnix::Root::parse(&src).ok().expect("failed to parse input");
let category = "debug";
let desc = retrieve_description(&nix, &"Debug", category);
writeln!(output, "{}", desc).expect("Failed to write header");

for entry in collect_entries(nix, category) {
entry
.write_section(&Default::default(), &mut output)
.expect("Failed to write section")
}

let output = String::from_utf8(output).expect("not utf8");

insta::assert_snapshot!(output);
}

#[test]
fn test_arg_formatting() {
let mut output = Vec::new();
Expand Down
326 changes: 326 additions & 0 deletions src/snapshots/nixdoc__description_of_lib_debug.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,326 @@
---
source: src/main.rs
expression: output
---
# Debug {#sec-functions-library-debug}
Collection of functions useful for debugging
broken nix expressions.

* `trace`-like functions take two values, print
the first to stderr and return the second.
* `traceVal`-like functions take one argument
which both printed and returned.
* `traceSeq`-like functions fully evaluate their
traced value before printing (not just to “weak
head normal form” like trace does by default).
* Functions that end in `-Fn` take an additional
function as their first argument, which is applied
to the traced value before it is printed.

## `lib.debug.traceIf` {#function-library-lib.debug.traceIf}

**Type**: `traceIf :: bool -> string -> a -> a`

Conditionally trace the supplied message, based on a predicate.

`pred`

: Predicate to check


`msg`

: Message that should be traced


`x`

: Value to return


::: {.example #function-library-example-lib.debug.traceIf}
# `lib.debug.traceIf` usage example

```nix
traceIf true "hello" 3
trace: hello
=> 3
```
:::

## `lib.debug.traceValFn` {#function-library-lib.debug.traceValFn}

**Type**: `traceValFn :: (a -> b) -> a -> a`

Trace the supplied value after applying a function to it, and
return the original value.

`f`

: Function to apply


`x`

: Value to trace and return


::: {.example #function-library-example-lib.debug.traceValFn}
# `lib.debug.traceValFn` usage example

```nix
traceValFn (v: "mystring ${v}") "foo"
trace: mystring foo
=> "foo"
```
:::

## `lib.debug.traceVal` {#function-library-lib.debug.traceVal}

**Type**: `traceVal :: a -> a`

Trace the supplied value and return it.

::: {.example #function-library-example-lib.debug.traceVal}
# `lib.debug.traceVal` usage example

```nix
traceVal 42
# trace: 42
=> 42
```
:::

## `lib.debug.traceSeq` {#function-library-lib.debug.traceSeq}

**Type**: `traceSeq :: a -> b -> b`

`builtins.trace`, but the value is `builtins.deepSeq`ed first.

`x`

: The value to trace


`y`

: The value to return


::: {.example #function-library-example-lib.debug.traceSeq}
# `lib.debug.traceSeq` usage example

```nix
trace { a.b.c = 3; } null
trace: { a = <CODE>; }
=> null
traceSeq { a.b.c = 3; } null
trace: { a = { b = { c = 3; }; }; }
=> null
```
:::

## `lib.debug.traceSeqN` {#function-library-lib.debug.traceSeqN}

**Type**: `traceSeqN :: Int -> a -> b -> b`

Like `traceSeq`, but only evaluate down to depth n.
This is very useful because lots of `traceSeq` usages
lead to an infinite recursion.

`depth`

: Function argument


`x`

: Function argument


`y`

: Function argument


::: {.example #function-library-example-lib.debug.traceSeqN}
# `lib.debug.traceSeqN` usage example

```nix
traceSeqN 2 { a.b.c = 3; } null
trace: { a = { b = {…}; }; }
=> null
```
:::

## `lib.debug.traceValSeqFn` {#function-library-lib.debug.traceValSeqFn}

A combination of `traceVal` and `traceSeq` that applies a
provided function to the value to be traced after `deepSeq`ing
it.

`f`

: Function to apply


`v`

: Value to trace


## `lib.debug.traceValSeq` {#function-library-lib.debug.traceValSeq}

A combination of `traceVal` and `traceSeq`.

## `lib.debug.traceValSeqNFn` {#function-library-lib.debug.traceValSeqNFn}

A combination of `traceVal` and `traceSeqN` that applies a
provided function to the value to be traced.

`f`

: Function to apply


`depth`

: Function argument


`v`

: Value to trace


## `lib.debug.traceValSeqN` {#function-library-lib.debug.traceValSeqN}

A combination of `traceVal` and `traceSeqN`.

## `lib.debug.traceFnSeqN` {#function-library-lib.debug.traceFnSeqN}

Trace the input and output of a function `f` named `name`,
both down to `depth`.

This is useful for adding around a function call,
to see the before/after of values as they are transformed.

`depth`

: Function argument


`name`

: Function argument


`f`

: Function argument


`v`

: Function argument


::: {.example #function-library-example-lib.debug.traceFnSeqN}
# `lib.debug.traceFnSeqN` usage example

```nix
traceFnSeqN 2 "id" (x: x) { a.b.c = 3; }
trace: { fn = "id"; from = { a.b = {…}; }; to = { a.b = {…}; }; }
=> { a.b.c = 3; }
```
:::

## `lib.debug.runTests` {#function-library-lib.debug.runTests}

**Type**:
```
runTests :: {
tests = [ String ];
${testName} :: {
expr :: a;
expected :: a;
};
}
->
[
{
name :: String;
expected :: a;
result :: a;
}
]
```

Evaluates a set of tests.

A test is an attribute set `{expr, expected}`,
denoting an expression and its expected result.

The result is a `list` of __failed tests__, each represented as
`{name, expected, result}`,

- expected
- What was passed as `expected`
- result
- The actual `result` of the test

Used for regression testing of the functions in lib; see
tests.nix for more examples.

Important: Only attributes that start with `test` are executed.

- If you want to run only a subset of the tests add the attribute `tests = ["testName"];`

`tests`

: Tests to run


::: {.example #function-library-example-lib.debug.runTests}
# `lib.debug.runTests` usage example

```nix
runTests {
testAndOk = {
expr = lib.and true false;
expected = false;
};
testAndFail = {
expr = lib.and true false;
expected = true;
};
}
->
[
{
name = "testAndFail";
expected = true;
result = false;
}
]
```
:::

## `lib.debug.testAllTrue` {#function-library-lib.debug.testAllTrue}

Create a test assuming that list elements are `true`.

`expr`

: Function argument


::: {.example #function-library-example-lib.debug.testAllTrue}
# `lib.debug.testAllTrue` usage example

```nix
{ testX = allTrue [ true ]; }
```
:::


Loading