Repository: google/yamlfmt (go)

Issue:
Support for "3" as an indent value
After fifteen years of using it, I can't believe my insane choice has basically just worked with everything I've tried it with ... until now.

Finally, a tool that doesn't handle threesp indentation well. I'm almost thankful, I've been waiting for this for so long.

So, at the moment, as far as I can tell, there's no difference between `indent: 2` and `indent: 3`. It seems to be a noop. Unsure if this is a side-effect of some other behaviour, or if the value is intentionally constrained to `2` or `4`?

Ideally, if you were bored enough to go out of your way to implement a feature that probably literally nobody but me would use, I'd like to see the `-` for list-items embedded _in_ the indentation, instead of _after_ it (so, not *quite* indentless arrays, but array-delimeter-recesses-into-indentation, which is indistinguishable for twosp indents):

```yaml
 - name: secure ssh configuration part 2
   become: true
   lineinfile:
      dest: /etc/ssh/sshd_config
      regexp: "{{ item.regexp }}"
      line: "{{ item.line }}"
   loop:
    - {regexp: '^AllowGroups', line: 'AllowGroups sshusers'}
    - {regexp: '^ClientAliveCountMax', line: 'ClientAliveCountMax 0'}
    - {regexp: '^ClientAliveInterval', line: 'ClientAliveInterval 300'}
    - {regexp: '^ListenAddress', line: 'ListenAddress 0.0.0.0'}
   ...
    - {regexp: '^LoginGraceTime', line: 'LoginGraceTime 30'}
   notify: restart ssh service
```

Anyway, I'm not delusional enough to see extra implementation work to go into this for me; I leave this Issue primiarly as a reminder to myself incase I get annoyed enough to come patch it myself ... and as a battle-cry for those strong few of us using the objectively best, middle-ground indentation setting. 💪 (Just sayin'.)

Pull request description:
add array indent functionality
Fixes #237 

This PR makes use of the new functionality in the yaml library to allow alternate array indents and indenting the root array.

Patch:
diff --git a/docs/config-file.md b/docs/config-file.md
index 553ba1f..46d6ee1 100644
--- a/docs/config-file.md
+++ b/docs/config-file.md
@@ -86,6 +86,8 @@ The basic formatter is a barebones formatter that simply takes the data provided
 | `trim_trailing_whitespace`  | bool           | false   | Trim trailing whitespace from lines. |
 | `eof_newline`               | bool           | false   | Always add a newline at end of file. Useful in the scenario where `retain_line_breaks` is disabled but the trailing newline is still needed. |
 | `strip_directives`          | bool           | false   | [YAML Directives](https://yaml.org/spec/1.2.2/#3234-directives) are not supported by this formatter. This feature will attempt to strip the directives before formatting and put them back. [Use this feature at your own risk.](#strip_directives) |
+| `array_indent`              | int            | = indent | Set a different indentation level for block sequences specifically. |
+| `indent_root_array`         | int            | false   | Tells the formatter to indent an array that is at the lowest indentation level of the document. |
 
 ## Additional Notes
 
diff --git a/formatters/basic/config.go b/formatters/basic/config.go
index ae9b689..82e67eb 100644
--- a/formatters/basic/config.go
+++ b/formatters/basic/config.go
@@ -35,6 +35,8 @@ type Config struct {
 	TrimTrailingWhitespace bool                   `mapstructure:"trim_trailing_whitespace"`
 	EOFNewline             bool                   `mapstructure:"eof_newline"`
 	StripDirectives        bool                   `mapstructure:"strip_directives"`
+	ArrayIndent            int                    `mapstructure:"array_indent"`
+	IndentRootArray        bool                   `mapstructure:"indent_root_array"`
 }
 
 func DefaultConfig() *Config {
diff --git a/formatters/basic/formatter.go b/formatters/basic/formatter.go
index 3cf0265..26bcc45 100644
--- a/formatters/basic/formatter.go
+++ b/formatters/basic/formatter.go
@@ -114,6 +114,11 @@ func (f *BasicFormatter) getNewEncoder(buf *bytes.Buffer) *yaml.Encoder {
 	e.SetDropMergeTag(f.Config.DropMergeTag)
 	e.SetPadLineComments(f.Config.PadLineComments)
 
+	if f.Config.ArrayIndent > 0 {
+		e.SetArrayIndent(f.Config.ArrayIndent)
+	}
+	e.SetIndentRootArray(f.Config.IndentRootArray)
+
 	return e
 }
 


Test patch:
diff --git a/formatters/basic/formatter_test.go b/formatters/basic/formatter_test.go
index 59bc20a..17b4077 100644
--- a/formatters/basic/formatter_test.go
+++ b/formatters/basic/formatter_test.go
@@ -363,3 +363,41 @@ func TestStripDirectives(t *testing.T) {
 	_, err := f.Format([]byte(yml))
 	assert.NilErr(t, err)
 }
+
+func TestArrayIndent(t *testing.T) {
+	config := basic.DefaultConfig()
+	config.ArrayIndent = 1
+	f := newFormatter(config)
+
+	yml := `a:
+  - 1
+  - 2
+`
+	expectedYml := `a:
+ - 1
+ - 2
+`
+
+	result, err := f.Format([]byte(yml))
+	assert.NilErr(t, err)
+	resultStr := string(result)
+	if resultStr != expectedYml {
+		t.Fatalf("expected: '%s', got: '%s'", expectedYml, result)
+	}
+}
+
+func TestIndentRootArray(t *testing.T) {
+	config := basic.DefaultConfig()
+	config.IndentRootArray = true
+	f := newFormatter(config)
+
+	yml := "- 1\n"
+	expectedYml := "  - 1\n"
+
+	result, err := f.Format([]byte(yml))
+	assert.NilErr(t, err)
+	resultStr := string(result)
+	if resultStr != expectedYml {
+		t.Fatalf("expected: '%s', got: '%s'", expectedYml, result)
+	}
+}
diff --git a/integrationtest/command/testdata/print_conf_file/stdout/stdout.txt b/integrationtest/command/testdata/print_conf_file/stdout/stdout.txt
index a1172e5..c63453f 100644
--- a/integrationtest/command/testdata/print_conf_file/stdout/stdout.txt
+++ b/integrationtest/command/testdata/print_conf_file/stdout/stdout.txt
@@ -13,11 +13,13 @@ match_type: doublestar
 output_format: default
 regex_exclude: []
 formatter:
+    array_indent: 0
     disallow_anchors: false
     drop_merge_tag: false
     eof_newline: false
     include_document_start: true
     indent: 2
+    indent_root_array: false
     indentless_arrays: false
     line_ending: crlf
     max_line_length: 0
diff --git a/integrationtest/command/testdata/print_conf_flags/stdout/stdout.txt b/integrationtest/command/testdata/print_conf_flags/stdout/stdout.txt
index 9c73e36..a17cd94 100644
--- a/integrationtest/command/testdata/print_conf_flags/stdout/stdout.txt
+++ b/integrationtest/command/testdata/print_conf_flags/stdout/stdout.txt
@@ -12,11 +12,13 @@ match_type: standard
 output_format: default
 regex_exclude: []
 formatter:
+    array_indent: 0
     disallow_anchors: false
     drop_merge_tag: false
     eof_newline: false
     include_document_start: false
     indent: 2
+    indent_root_array: false
     indentless_arrays: false
     line_ending: lf
     max_line_length: 0
diff --git a/integrationtest/command/testdata/print_conf_flags_and_file/stdout/stdout.txt b/integrationtest/command/testdata/print_conf_flags_and_file/stdout/stdout.txt
index 01be6e7..0f4e277 100644
--- a/integrationtest/command/testdata/print_conf_flags_and_file/stdout/stdout.txt
+++ b/integrationtest/command/testdata/print_conf_flags_and_file/stdout/stdout.txt
@@ -13,11 +13,13 @@ match_type: doublestar
 output_format: default
 regex_exclude: []
 formatter:
+    array_indent: 0
     disallow_anchors: false
     drop_merge_tag: false
     eof_newline: false
     include_document_start: true
     indent: 2
+    indent_root_array: false
     indentless_arrays: false
     line_ending: crlf
     max_line_length: 0