diff --git a/.gitignore b/.gitignore index 0196246..762c3ce 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ /target/ **/*.rs.bk +.direnv +result* diff --git a/flake.nix b/flake.nix index 15b94e8..d796b3a 100644 --- a/flake.nix +++ b/flake.nix @@ -45,6 +45,7 @@ cargo-insta clippy rustfmt + rustc ]; }; }); diff --git a/src/commonmark.rs b/src/commonmark.rs index 4fa13b7..9197130 100644 --- a/src/commonmark.rs +++ b/src/commonmark.rs @@ -113,7 +113,11 @@ impl ManualEntry { // (type signature) if let Some(t) = &self.fn_type { - writeln!(writer, "**Type**: `{}`\n", t)?; + if t.lines().count() > 1 { + writeln!(writer, "**Type**:\n```\n{}\n```\n", t)?; + } else { + writeln!(writer, "**Type**: `{}`\n", t)?; + } } // Primary doc string diff --git a/src/main.rs b/src/main.rs index e6d0524..1e6f667 100644 --- a/src/main.rs +++ b/src/main.rs @@ -30,6 +30,7 @@ use rnix::{ }; use rowan::{ast::AstNode, WalkEvent}; use std::fs; +use textwrap::dedent; use std::collections::HashMap; use std::io; @@ -172,7 +173,34 @@ fn retrieve_doc_item(node: &AttrpathValue) -> Option { }) } -/// *Really* dumb, mutable, hacky doc comment "parser". +/// Dedent everything but the first line, whose indentation gets fully removed all the time +/// +/// A doc comment like this in Nix: +/// +/// { +/// /* foo is +/// the value: +/// 10 +/// */ +/// foo = 10; +/// } +/// +/// The parser turns this into "foo is\n the value:\n 10\n" where the first +/// line has no leading indentation, but the rest do +/// +/// To align all lines to the same indentation, while preserving the +/// formatting, we dedent all but the first line, while stripping any potential +/// indentation from the first line. +fn handle_indentation(raw: &str) -> Option { + let result: String = match raw.split_once('\n') { + Some((first, rest)) => format!("{}\n{}", first.trim(), dedent(rest)), + None => raw.into(), + }; + + Some(result.trim().to_owned()).filter(|s| !s.is_empty()) +} + +/// Dumb, mutable, hacky doc comment "parser". fn parse_doc_comment(raw: &str) -> DocComment { enum ParseState { Doc, @@ -180,43 +208,36 @@ fn parse_doc_comment(raw: &str) -> DocComment { Example, } - let mut doc = String::new(); - let mut doc_type = String::new(); - let mut example = String::new(); let mut state = ParseState::Doc; - for line in raw.trim().lines() { - let mut line = line.trim(); + // Split the string into three parts, docs, type and example + let mut doc_str = String::new(); + let mut type_str = String::new(); + let mut example_str = String::new(); - if line.starts_with("Type:") { + for line in raw.split_inclusive('\n') { + let trimmed_line = line.trim(); + if let Some(suffix) = trimmed_line.strip_prefix("Type:") { state = ParseState::Type; - line = &line[5..]; // trim 'Type:' - } - - if line.starts_with("Example:") { + type_str.push_str(suffix); + type_str.push('\n'); + } else if let Some(suffix) = trimmed_line.strip_prefix("Example:") { state = ParseState::Example; - line = &line[8..]; // trim 'Example:' - } - - match state { - ParseState::Type => doc_type.push_str(line.trim()), - ParseState::Doc => { - doc.push_str(line.trim()); - doc.push('\n'); - } - ParseState::Example => { - example.push_str(line.trim()); - example.push('\n'); + example_str.push_str(suffix); + example_str.push('\n'); + } else { + match state { + ParseState::Doc => doc_str.push_str(line), + ParseState::Type => type_str.push_str(line), + ParseState::Example => example_str.push_str(line), } } } - let f = |s: String| if s.is_empty() { None } else { Some(s) }; - DocComment { - doc: doc.trim().into(), - doc_type: f(doc_type), - example: f(example), + doc: handle_indentation(&doc_str).unwrap_or(String::new()), + doc_type: handle_indentation(&type_str), + example: handle_indentation(&example_str), } } diff --git a/src/snapshots/nixdoc__main.snap b/src/snapshots/nixdoc__main.snap index e686ef1..303d925 100644 --- a/src/snapshots/nixdoc__main.snap +++ b/src/snapshots/nixdoc__main.snap @@ -689,8 +689,8 @@ assume a shell that understands Bash syntax (e.g. Bash or ZSH). ```nix '' -${toShellVar "foo" "some string"} -[[ "$foo" == "some string" ]] + ${toShellVar "foo" "some string"} + [[ "$foo" == "some string" ]] '' ``` ::: @@ -714,11 +714,11 @@ using `toShellVar`. ```nix let -foo = "value"; -bar = foo; + foo = "value"; + bar = foo; in '' -${toShellVars { inherit foo bar; }} -[[ "$foo" == "$bar" ]] + ${toShellVars { inherit foo bar; }} + [[ "$foo" == "$bar" ]] '' ``` ::: @@ -1092,7 +1092,13 @@ Located at [lib/strings.nix:735](https://github.com/NixOS/nixpkgs/blob/580dd2124 ## `lib.strings.mesonOption` {#function-library-lib.strings.mesonOption} -**Type**: `mesonOption :: string -> string -> string@param feature The feature to be set@param value The desired value` +**Type**: +``` +mesonOption :: string -> string -> string + +@param feature The feature to be set +@param value The desired value +``` Create a -D= string that can be passed to typical Meson invocations. @@ -1120,7 +1126,13 @@ Located at [lib/strings.nix:754](https://github.com/NixOS/nixpkgs/blob/580dd2124 ## `lib.strings.mesonBool` {#function-library-lib.strings.mesonBool} -**Type**: `mesonBool :: string -> bool -> string@param condition The condition to be made true or false@param flag The controlling flag of the condition` +**Type**: +``` +mesonBool :: string -> bool -> string + +@param condition The condition to be made true or false +@param flag The controlling flag of the condition +``` Create a -D={true,false} string that can be passed to typical Meson invocations. @@ -1150,7 +1162,13 @@ Located at [lib/strings.nix:773](https://github.com/NixOS/nixpkgs/blob/580dd2124 ## `lib.strings.mesonEnable` {#function-library-lib.strings.mesonEnable} -**Type**: `mesonEnable :: string -> bool -> string@param feature The feature to be enabled or disabled@param flag The controlling flag` +**Type**: +``` +mesonEnable :: string -> bool -> string + +@param feature The feature to be enabled or disabled +@param flag The controlling flag +``` Create a -D={enabled,disabled} string that can be passed to typical Meson invocations. @@ -1379,7 +1397,7 @@ floatToString 0.000001 => "0.000001" floatToString 0.0000001 => trace: warning: Imprecise conversion from float to string 0.000000 -"0.000000" + "0.000000" ``` ::: @@ -1529,12 +1547,12 @@ NOTE: This function is not performant and should be avoided. ```nix readPathsFromFile /prefix -./pkgs/development/libraries/qt-5/5.4/qtbase/series + ./pkgs/development/libraries/qt-5/5.4/qtbase/series => [ "/prefix/dlopen-resolv.patch" "/prefix/tzdir.patch" -"/prefix/dlopen-libXcursor.patch" "/prefix/dlopen-openssl.patch" -"/prefix/dlopen-dbus.patch" "/prefix/xdg-config-dirs.patch" -"/prefix/nix-profiles-library-paths.patch" -"/prefix/compose-search-path.patch" ] + "/prefix/dlopen-libXcursor.patch" "/prefix/dlopen-openssl.patch" + "/prefix/dlopen-dbus.patch" "/prefix/xdg-config-dirs.patch" + "/prefix/nix-profiles-library-paths.patch" + "/prefix/compose-search-path.patch" ] ``` :::