Skip to content

Commit

Permalink
cmd/shfmt: add a -fn printer option
Browse files Browse the repository at this point in the history
This option allows placing a function's opening brace on a separate line,
which brings one's style a bit closer to K&R. It can also be useful to quickly
find or jump to function definitions.

The same option is exposed in the syntax package.

Fixes #229.
  • Loading branch information
MorganAntonsson authored Feb 17, 2020
1 parent 7a8db93 commit c3b7a40
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 13 deletions.
15 changes: 9 additions & 6 deletions cmd/shfmt/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,12 @@ var (
langStr = flag.String("ln", "", "")
posix = flag.Bool("p", false, "")

indent = flag.Uint("i", 0, "")
binNext = flag.Bool("bn", false, "")
caseIndent = flag.Bool("ci", false, "")
spaceRedirs = flag.Bool("sr", false, "")
keepPadding = flag.Bool("kp", false, "")
indent = flag.Uint("i", 0, "")
binNext = flag.Bool("bn", false, "")
caseIndent = flag.Bool("ci", false, "")
spaceRedirs = flag.Bool("sr", false, "")
keepPadding = flag.Bool("kp", false, "")
functionNewLine = flag.Bool("fn", false, "")

toJSON = flag.Bool("tojson", false, "")

Expand Down Expand Up @@ -91,6 +92,7 @@ Printer options:
-ci switch cases will be indented
-sr redirect operators will be followed by a space
-kp keep column alignment paddings
-fn function opening braces are placed on a separate line
Utilities:
Expand All @@ -116,7 +118,7 @@ Utilities:
}
flag.Visit(func(f *flag.Flag) {
switch f.Name {
case "ln", "p", "i", "bn", "ci", "sr", "kp":
case "ln", "p", "i", "bn", "ci", "sr", "kp", "fn":
useEditorConfig = false
}
})
Expand Down Expand Up @@ -145,6 +147,7 @@ Utilities:
syntax.SwitchCaseIndent(*caseIndent)(printer)
syntax.SpaceRedirects(*spaceRedirs)(printer)
syntax.KeepPadding(*keepPadding)(printer)
syntax.FunctionNewLine(*functionNewLine)(printer)
}

if os.Getenv("FORCE_COLOR") == "true" {
Expand Down
24 changes: 17 additions & 7 deletions syntax/printer.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ func Minify(enabled bool) PrinterOption {
return func(p *Printer) { p.minify = enabled }
}

// FunctionNewLine will place function braces on a new line.
func FunctionNewLine(enabled bool) PrinterOption {
return func(p *Printer) { p.functionNewLine = enabled }
}

// NewPrinter allocates a new Printer and applies any number of options.
func NewPrinter(opts ...PrinterOption) *Printer {
p := &Printer{
Expand Down Expand Up @@ -188,12 +193,13 @@ type Printer struct {
tabWriter *tabwriter.Writer
cols colCounter

indentSpaces uint
binNextLine bool
swtCaseIndent bool
spaceRedirects bool
keepPadding bool
minify bool
indentSpaces uint
binNextLine bool
swtCaseIndent bool
spaceRedirects bool
keepPadding bool
minify bool
functionNewLine bool

wantSpace bool
wantNewline bool
Expand Down Expand Up @@ -962,6 +968,8 @@ func (p *Printer) command(cmd Command, redirs []*Redirect) (startRedirs int) {
case *Block:
p.WriteByte('{')
p.wantSpace = true
// Forbid "foo()\n{ bar; }"
p.wantNewline = p.wantNewline || p.functionNewLine
p.nestedStmts(x.Stmts, x.Last, x.Rbrace)
p.semiRsrv("}", x.Rbrace)
case *IfClause:
Expand Down Expand Up @@ -1040,7 +1048,9 @@ func (p *Printer) command(cmd Command, redirs []*Redirect) (startRedirs int) {
}
p.writeLit(x.Name.Value)
p.WriteString("()")
if !p.minify {
if p.functionNewLine {
p.newline(Pos{})
} else if !p.minify {
p.space()
}
p.line = x.Body.Pos().Line()
Expand Down
29 changes: 29 additions & 0 deletions syntax/printer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,35 @@ func TestPrintSwitchCaseIndent(t *testing.T) {
}
}

func TestPrintFunctionNewLine(t *testing.T) {
t.Parallel()
tests := [...]printCase{
{
"foo() { bar; }",
"foo()\n{\n\tbar\n}",
},
{
"foo()\n{ bar; }",
"foo()\n{\n\tbar\n}",
},
{
"foo()\n\n{\n\n\tbar\n}",
"foo()\n{\n\n\tbar\n}",
},
{
"function foo {\n\tbar\n}",
"function foo()\n{\n\tbar\n}",
},
}
parser := NewParser(KeepComments(true))
printer := NewPrinter(FunctionNewLine(true))
for i, tc := range tests {
t.Run(fmt.Sprintf("%03d", i), func(t *testing.T) {
printTest(t, parser, printer, tc.in, tc.want)
})
}
}

func TestPrintSpaceRedirects(t *testing.T) {
t.Parallel()
tests := [...]printCase{
Expand Down

0 comments on commit c3b7a40

Please sign in to comment.