diff --git a/Sources/Markdown/Walker/Walkers/MarkupFormatter.swift b/Sources/Markdown/Walker/Walkers/MarkupFormatter.swift index 310280a5..fedfe51b 100644 --- a/Sources/Markdown/Walker/Walkers/MarkupFormatter.swift +++ b/Sources/Markdown/Walker/Walkers/MarkupFormatter.swift @@ -238,6 +238,21 @@ public struct MarkupFormatter: MarkupWalker { /// Precede Doxygen commands with an at-sign (`@`). case at = "@" } + + public enum IndentationStyle: String, CaseIterable { + case spaces = "spaces" // use spaces for indentation + case tabs = "tabs" // Use tab characters for indentation + + /// Generates an indentation string based on the current indentation style. + func indentation() -> String { + switch self { + case .spaces: + return String(" ") + case .tabs: + return String("\t") + } + } + } // MARK: Option Properties @@ -253,6 +268,7 @@ public struct MarkupFormatter: MarkupWalker { var preferredLineLimit: PreferredLineLimit? var customLinePrefix: String var doxygenCommandPrefix: DoxygenCommandPrefix + var indentationStyle: IndentationStyle /** Create a set of formatting options to use when printing an element. @@ -269,6 +285,8 @@ public struct MarkupFormatter: MarkupWalker { - preferredHeadingStyle: The preferred heading style. - lineLimit: The preferred maximum line length and method for splitting ``Text`` elements in an attempt to maintain that line length. - customLinePrefix: An addition prefix to print at the start of each line, useful for adding documentation comment markers. + - indentationStyle: Whether to use spaces or tabs when indenting. + */ public init(unorderedListMarker: UnorderedListMarker = .dash, orderedListNumerals: OrderedListNumerals = .allSame(1), @@ -281,7 +299,8 @@ public struct MarkupFormatter: MarkupWalker { preferredHeadingStyle: PreferredHeadingStyle = .atx, preferredLineLimit: PreferredLineLimit? = nil, customLinePrefix: String = "", - doxygenCommandPrefix: DoxygenCommandPrefix = .backslash) { + doxygenCommandPrefix: DoxygenCommandPrefix = .backslash, + indentationStyle: IndentationStyle = .spaces) { self.unorderedListMarker = unorderedListMarker self.orderedListNumerals = orderedListNumerals self.useCodeFence = useCodeFence @@ -296,6 +315,7 @@ public struct MarkupFormatter: MarkupWalker { self.thematicBreakLength = max(3, thematicBreakLength) self.customLinePrefix = customLinePrefix self.doxygenCommandPrefix = doxygenCommandPrefix + self.indentationStyle = indentationStyle } /// The default set of formatting options. @@ -431,12 +451,12 @@ public struct MarkupFormatter: MarkupWalker { prefix += "> " } else if element is UnorderedList { if unorderedListCount > 0 { - prefix += " " + prefix += formattingOptions.indentationStyle.indentation() } unorderedListCount += 1 } else if element is OrderedList { if orderedListCount > 0 { - prefix += " " + prefix += formattingOptions.indentationStyle.indentation() } orderedListCount += 1 } else if !(element is ListItem), @@ -461,11 +481,12 @@ public struct MarkupFormatter: MarkupWalker { // Unordered list markers are of fixed length. prefix += " " } else if let numeralPrefix = numeralPrefix(for: parentListItem) { + // I don't know exactly what will happen when this produces an indent of 4 or more spaces. prefix += String(repeating: " ", count: numeralPrefix.count) } } if element.parent is BlockDirective { - prefix += " " + prefix += formattingOptions.indentationStyle.indentation() } } return prefix diff --git a/Tools/markdown-tool/Commands/FormatCommand.swift b/Tools/markdown-tool/Commands/FormatCommand.swift index 4f81c791..4d85690c 100644 --- a/Tools/markdown-tool/Commands/FormatCommand.swift +++ b/Tools/markdown-tool/Commands/FormatCommand.swift @@ -52,6 +52,7 @@ extension MarkupFormatter.Options.ThematicBreakCharacter: ExpressibleByArgument extension MarkupFormatter.Options.EmphasisMarker: ExpressibleByArgument {} extension MarkupFormatter.Options.PreferredHeadingStyle: ExpressibleByArgument {} extension MarkupFormatter.Options.PreferredLineLimit.SplittingElement: ExpressibleByArgument {} +extension MarkupFormatter.Options.IndentionStyle: ExpressibleByArgument {} extension MarkdownCommand { /** @@ -108,6 +109,9 @@ extension MarkdownCommand { @Option(help: "The kind of element to use to split text elements while enforcing --preferred-maximum-line-length; choices: \(MarkupFormatter.Options.PreferredLineLimit.SplittingElement.allCases.map { $0.rawValue }.joined(separator: ", "))") var lineSplittingElement: MarkupFormatter.Options.PreferredLineLimit.SplittingElement = .softBreak + @Option(help: "The indentation style to use when emitting indented blocks; choices:\(MarkupFormatter.Options.IndentationStyle.allCases.map { $0.rawValue }.joined(separator: ", "))") + var indentationStyle: MarkupFormatter.Options.IndentationStyle = .spaces + @Option(help: "Prepend this prefix to every line") var customLinePrefix: String = "" @@ -232,7 +236,8 @@ extension MarkdownCommand { condenseAutolinks: condenseAutolinks, preferredHeadingStyle: preferredHeadingStyle, preferredLineLimit: preferredLineLimit, - customLinePrefix: customLinePrefix) + customLinePrefix: customLinePrefix, + indentationStyle: indentationStyle) let formatted = document.format(options: formatOptions) print(formatted) if checkStructuralEquivalence {