wdl_doc/
command_section.rs

1//! A module containing an extension trait for the [`CommandSection`] AST type.
2
3use wdl_ast::AstNode;
4use wdl_ast::v1::CommandPart;
5use wdl_ast::v1::CommandSection;
6use wdl_ast::v1::StrippedCommandPart;
7
8/// An extension trait for the [`CommandSection`] type that provides
9/// functionality for rendering the command section as a script string.
10pub trait CommandSectionExt {
11    /// Returns the command section as a script string.
12    ///
13    /// This is a concatenation of all text parts and placeholders with common
14    /// whitespace stripped (including whitespace common to the placeholders,
15    /// which is typically ignored as semantically meaningless).
16    fn script(&self) -> String;
17}
18
19impl CommandSectionExt for CommandSection {
20    fn script(&self) -> String {
21        let common_whitespace = self.count_whitespace();
22        match self.strip_whitespace() {
23            Some(v) => v
24                .into_iter()
25                .map(|s| match s {
26                    StrippedCommandPart::Text(text) => text,
27                    StrippedCommandPart::Placeholder(placeholder) => {
28                        let common_whitespace =
29                            common_whitespace.expect("common whitespace should be present");
30                        let placeholder = placeholder.text().to_string();
31                        placeholder
32                            .lines()
33                            .map(|line| {
34                                if line.starts_with(&" ".repeat(common_whitespace))
35                                    || line.starts_with(&"\t".repeat(common_whitespace))
36                                {
37                                    &line[common_whitespace..]
38                                } else {
39                                    line
40                                }
41                            })
42                            .collect::<Vec<_>>()
43                            .join("\n")
44                    }
45                })
46                .collect(),
47            None => self
48                .parts()
49                .map(|p| match p {
50                    CommandPart::Text(text) => {
51                        let mut buffer = String::new();
52                        text.unescape_to(self.is_heredoc(), &mut buffer);
53                        buffer
54                    }
55                    CommandPart::Placeholder(placeholder) => placeholder.text().to_string(),
56                })
57                .collect(),
58        }
59    }
60}