Repository: bytecodealliance/wasm-tools (rust)

Issue:
`wasmprinter`: make indent character configurable
I find the indentation is not very noticeable when reading nested blocks.

I wish it could be increased to 8 spaces.

Do I just need to modify this place and add the configuration item:

https://github.com/bytecodealliance/wasm-tools/blob/57b1acee689e49f43338e4efb15b65e9f922831d/crates/wasmprinter/src/lib.rs#L1416

Pull request description:
[wasmprinter] support custom indent text
Close #1962 

Patch:
diff --git a/crates/wasmprinter/src/lib.rs b/crates/wasmprinter/src/lib.rs
index b7844bf8..ac9deb25 100644
--- a/crates/wasmprinter/src/lib.rs
+++ b/crates/wasmprinter/src/lib.rs
@@ -50,12 +50,25 @@ pub fn print_bytes(wasm: impl AsRef<[u8]>) -> Result<String> {
 ///
 /// This structure is used to control the overal structure of how wasm binaries
 /// are printed and tweaks various ways that configures the output.
-#[derive(Debug, Default)]
+#[derive(Debug)]
 pub struct Config {
     print_offsets: bool,
     print_skeleton: bool,
     name_unnamed: bool,
     fold_instructions: bool,
+    indent_text: String,
+}
+
+impl Default for Config {
+    fn default() -> Self {
+        Self {
+            print_offsets: false,
+            print_skeleton: false,
+            name_unnamed: false,
+            fold_instructions: false,
+            indent_text: "  ".to_string(),
+        }
+    }
 }
 
 /// This structure is the actual structure that prints WebAssembly binaries.
@@ -226,6 +239,17 @@ impl Config {
         self
     }
 
+    /// Select the string to use when indenting.
+    ///
+    /// The indent allowed here are arbitrary and unchecked. You should enter
+    /// blank text like `" "` or `"\t"`, rather than something like `"(;;)"`.
+    ///
+    /// The default setting is double spaces `" "`
+    pub fn indent_text(&mut self, text: impl Into<String>) -> &mut Self {
+        self.indent_text = text.into();
+        self
+    }
+
     /// Prints a WebAssembly binary into a `String`
     ///
     /// This function takes an entire `wasm` binary blob and will print it to
@@ -1413,7 +1437,7 @@ impl Printer<'_, '_> {
         // reasonable to avoid generating hundreds of megabytes of whitespace
         // for small-ish modules that have deep-ish nesting.
         for _ in 0..self.nesting.min(MAX_NESTING_TO_PRINT) {
-            self.result.write_str("  ")?;
+            self.result.write_str(&self.config.indent_text)?;
         }
         Ok(())
     }
diff --git a/crates/wasmprinter/src/operator.rs b/crates/wasmprinter/src/operator.rs
index 5b6f728d..a87df506 100644
--- a/crates/wasmprinter/src/operator.rs
+++ b/crates/wasmprinter/src/operator.rs
@@ -1453,10 +1453,8 @@ impl OpPrinter for PrintOperatorFolded<'_, '_, '_, '_> {
         let mut buf_color = PrintTermcolor(Ansi::new(Vec::new()));
         let mut buf_nocolor = PrintTermcolor(NoColor::new(Vec::new()));
         let internal_config = Config {
-            print_offsets: false,
-            print_skeleton: false,
             name_unnamed: self.printer.config.name_unnamed,
-            fold_instructions: false,
+            ..Default::default()
         };
         let mut internal_printer = Printer {
             config: &internal_config,
diff --git a/crates/wit-parser/src/lib.rs b/crates/wit-parser/src/lib.rs
index cb8b2f4e..a3370cf5 100644
--- a/crates/wit-parser/src/lib.rs
+++ b/crates/wit-parser/src/lib.rs
@@ -148,7 +148,7 @@ struct InterfaceSpan {
 
 #[derive(Debug, Copy, Clone)]
 #[cfg_attr(feature = "serde", derive(Serialize))]
-#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
+#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
 pub enum AstItem {
     #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
     Interface(InterfaceId),
@@ -471,7 +471,7 @@ impl WorldKey {
 
 #[derive(Debug, Clone, PartialEq)]
 #[cfg_attr(feature = "serde", derive(Serialize))]
-#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
+#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
 pub enum WorldItem {
     /// An interface is being imported or exported from a world, indicating that
     /// it's a namespace of functions.
@@ -557,7 +557,7 @@ pub struct TypeDef {
 
 #[derive(Debug, Clone, PartialEq)]
 #[cfg_attr(feature = "serde", derive(Serialize))]
-#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
+#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
 pub enum TypeDefKind {
     Record(Record),
     Resource,
@@ -609,7 +609,7 @@ impl TypeDefKind {
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 #[cfg_attr(feature = "serde", derive(Serialize))]
-#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
+#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
 pub enum TypeOwner {
     /// This type was defined within a `world` block.
     #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
@@ -625,7 +625,7 @@ pub enum TypeOwner {
 
 #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
 #[cfg_attr(feature = "serde", derive(Serialize))]
-#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
+#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
 pub enum Handle {
     #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
     Own(TypeId),
@@ -886,7 +886,7 @@ pub struct Function {
 
 #[derive(Debug, Clone, PartialEq, Eq)]
 #[cfg_attr(feature = "serde", derive(Serialize))]
-#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
+#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
 pub enum FunctionKind {
     Freestanding,
     #[cfg_attr(feature = "serde", serde(serialize_with = "serialize_id"))]
@@ -1154,7 +1154,7 @@ fn find_futures_and_streams(resolve: &Resolve, ty: Type, results: &mut Vec<TypeI
 /// annotations were added to WIT.
 #[derive(Debug, Clone, PartialEq, Eq)]
 #[cfg_attr(feature = "serde", derive(serde_derive::Deserialize, Serialize))]
-#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
+#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
 pub enum Stability {
     /// `@since(version = 1.2.3)`
     ///
diff --git a/src/bin/wasm-tools/print.rs b/src/bin/wasm-tools/print.rs
index 08a15446..a88e2de9 100644
--- a/src/bin/wasm-tools/print.rs
+++ b/src/bin/wasm-tools/print.rs
@@ -30,6 +30,13 @@ pub struct Opts {
     /// Print instructions in the folded format.
     #[clap(short, long)]
     fold_instructions: bool,
+
+    /// The string to use when indenting.
+    #[clap(long)]
+    indent_text: Option<String>,
+    /// Number of spaces used for indentation, has lower priority than `--indent-text`
+    #[clap(long)]
+    indent: Option<usize>,
 }
 
 impl Opts {
@@ -45,6 +52,16 @@ impl Opts {
         config.print_skeleton(self.skeleton);
         config.name_unnamed(self.name_unnamed);
         config.fold_instructions(self.fold_instructions);
+        match self.indent_text.as_ref() {
+            Some(s) => {
+                config.indent_text(s);
+            }
+            None => {
+                if let Some(s) = self.indent {
+                    config.indent_text(&" ".repeat(s));
+                }
+            }
+        }
         self.io.output(wasm_tools::Output::Wat {
             wasm: &wasm,
             config,


Test patch:
diff --git a/crates/wit-parser/tests/ui/error-context.wit.json b/crates/wit-parser/tests/ui/error-context.wit.json
index 1a63f8fb..259755e7 100644
--- a/crates/wit-parser/tests/ui/error-context.wit.json
+++ b/crates/wit-parser/tests/ui/error-context.wit.json
@@ -33,14 +33,14 @@
   "types": [
     {
       "name": "t1",
-      "kind": "errorcontext",
+      "kind": "error-context",
       "owner": {
         "interface": 0
       }
     },
     {
       "name": null,
-      "kind": "errorcontext",
+      "kind": "error-context",
       "owner": null
     },
     {
diff --git a/tests/cli/print-custom-indent-width.wat b/tests/cli/print-custom-indent-width.wat
new file mode 100644
index 00000000..b14203c6
--- /dev/null
+++ b/tests/cli/print-custom-indent-width.wat
@@ -0,0 +1,9 @@
+;; RUN: print --indent 4 %
+
+(;@0     ;) (module
+(;@b     ;)   (type (;0;) (func (param i32) (result i32)))
+(;@1f    ;)   (func (;0;) (type 0) (param i32) (result i32)
+(;@20    ;)     local.get 0
+              )
+(;@17    ;)   (export "f" (func 0))
+            )
\ No newline at end of file
diff --git a/tests/cli/print-custom-indent-width.wat.stdout b/tests/cli/print-custom-indent-width.wat.stdout
new file mode 100644
index 00000000..11b32478
--- /dev/null
+++ b/tests/cli/print-custom-indent-width.wat.stdout
@@ -0,0 +1,7 @@
+(module
+    (type (;0;) (func (param i32) (result i32)))
+    (export "f" (func 0))
+    (func (;0;) (type 0) (param i32) (result i32)
+        local.get 0
+    )
+)
\ No newline at end of file