Skip to content

Commit

Permalink
Allow specifying --print-width in the CLI
Browse files Browse the repository at this point in the history
  • Loading branch information
kddnewton committed Jul 19, 2022
1 parent b5024c3 commit 509c29e
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 34 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,12 @@ If there are files with unformatted code, you will receive:
The listed files did not match the expected format.
```

To change the print width that you are checking against, specify the `--print-width` option, as in:

```sh
stree check --print-width=100 path/to/file.rb
```

### format

This command will output the formatted version of each of the listed files. Importantly, it will not write that content back to the source files. It is meant to display the formatted version only.
Expand All @@ -132,6 +138,12 @@ For a file that contains `1 + 1`, you will receive:
1 + 1
```

To change the print width that you are formatting with, specify the `--print-width` option, as in:

```sh
stree format --print-width=100 path/to/file.rb
```

### json

This command will output a JSON representation of the syntax tree that is functionally equivalent to the input. This is mostly used in contexts where you need to access the tree from JavaScript or serialize it over a network.
Expand Down Expand Up @@ -213,6 +225,12 @@ This will list every file that is being formatted. It will output light gray if
path/to/file.rb 0ms
```

To change the print width that you are writing with, specify the `--print-width` option, as in:

```sh
stree write --print-width=100 path/to/file.rb
```

## Library

Syntax Tree can be used as a library to access the syntax tree underlying Ruby source code.
Expand Down
7 changes: 6 additions & 1 deletion lib/syntax_tree.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ module SyntaxTree
HANDLERS = {}
HANDLERS.default = SyntaxTree

# This is the default print width when formatting. It can be overridden in the
# CLI by passing the --print-width option or here in the API by passing the
# optional second argument to ::format.
DEFAULT_PRINT_WIDTH = 80

# This is a hook provided so that plugins can register themselves as the
# handler for a particular file type.
def self.register_handler(extension, handler)
Expand All @@ -43,7 +48,7 @@ def self.parse(source)
end

# Parses the given source and returns the formatted source.
def self.format(source, maxwidth = 80)
def self.format(source, maxwidth = DEFAULT_PRINT_WIDTH)
formatter = Formatter.new(source, [], maxwidth)
parse(source).format(formatter)

Expand Down
103 changes: 70 additions & 33 deletions lib/syntax_tree/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,15 @@ class Check < Action
class UnformattedError < StandardError
end

attr_reader :print_width

def initialize(print_width:)
@print_width = print_width
end

def run(item)
source = item.source
raise UnformattedError if source != item.handler.format(source)
raise UnformattedError if source != item.handler.format(source, print_width)
rescue StandardError
warn("[#{Color.yellow("warn")}] #{item.filepath}")
raise
Expand All @@ -114,13 +120,19 @@ class Debug < Action
class NonIdempotentFormatError < StandardError
end

attr_reader :print_width

def initialize(print_width:)
@print_width = print_width
end

def run(item)
handler = item.handler

warning = "[#{Color.yellow("warn")}] #{item.filepath}"
formatted = handler.format(item.source)
formatted = handler.format(item.source, print_width)

raise NonIdempotentFormatError if formatted != handler.format(formatted)
raise NonIdempotentFormatError if formatted != handler.format(formatted, print_width)
rescue StandardError
warn(warning)
raise
Expand Down Expand Up @@ -148,8 +160,14 @@ def run(item)

# An action of the CLI that formats the input source and prints it out.
class Format < Action
attr_reader :print_width

def initialize(print_width:)
@print_width = print_width
end

def run(item)
puts item.handler.format(item.source)
puts item.handler.format(item.source, print_width)
end
end

Expand All @@ -173,12 +191,18 @@ def run(item)
# An action of the CLI that formats the input source and writes the
# formatted output back to the file.
class Write < Action
attr_reader :print_width

def initialize(print_width:)
@print_width = print_width
end

def run(item)
filepath = item.filepath
start = Time.now

source = item.source
formatted = item.handler.format(source)
formatted = item.handler.format(source, print_width)
File.write(filepath, formatted) if filepath != :stdin

color = source == formatted ? Color.gray(filepath) : filepath
Expand All @@ -194,63 +218,76 @@ def run(item)
# The help message displayed if the input arguments are not correctly
# ordered or formatted.
HELP = <<~HELP
#{Color.bold("stree ast [OPTIONS] [FILE]")}
#{Color.bold("stree ast [--plugins=...] [--print-width=NUMBER] FILE")}
Print out the AST corresponding to the given files
#{Color.bold("stree check [OPTIONS] [FILE]")}
#{Color.bold("stree check [--plugins=...] [--print-width=NUMBER] FILE")}
Check that the given files are formatted as syntax tree would format them
#{Color.bold("stree debug [OPTIONS] [FILE]")}
#{Color.bold("stree debug [--plugins=...] [--print-width=NUMBER] FILE")}
Check that the given files can be formatted idempotently
#{Color.bold("stree doc [OPTIONS] [FILE]")}
#{Color.bold("stree doc [--plugins=...] FILE")}
Print out the doc tree that would be used to format the given files
#{Color.bold("stree format [OPTIONS] [FILE]")}
#{Color.bold("stree format [--plugins=...] [--print-width=NUMBER] FILE")}
Print out the formatted version of the given files
#{Color.bold("stree json [OPTIONS] [FILE]")}
#{Color.bold("stree json [--plugins=...] FILE")}
Print out the JSON representation of the given files
#{Color.bold("stree match [OPTIONS] [FILE]")}
#{Color.bold("stree match [--plugins=...] FILE")}
Print out a pattern-matching Ruby expression that would match the given files
#{Color.bold("stree help")}
Display this help message
#{Color.bold("stree lsp [OPTIONS]")}
#{Color.bold("stree lsp [--plugins=...]")}
Run syntax tree in language server mode
#{Color.bold("stree version")}
Output the current version of syntax tree
#{Color.bold("stree write [OPTIONS] [FILE]")}
#{Color.bold("stree write [--plugins=...] [--print-width=NUMBER] FILE")}
Read, format, and write back the source of the given files
[OPTIONS]
--plugins=...
A comma-separated list of plugins to load.
--print-width=NUMBER
The maximum line width to use when formatting.
HELP

class << self
# Run the CLI over the given array of strings that make up the arguments
# passed to the invocation.
def run(argv)
name, *arguments = argv

# If there are any plugins specified on the command line, then load them
# by requiring them here. We do this by transforming something like
#
# stree format --plugins=haml template.haml
#
# into
#
# require "syntax_tree/haml"
#
if arguments.first&.start_with?("--plugins=")
plugins = arguments.shift[/^--plugins=(.*)$/, 1]
plugins.split(",").each { |plugin| require "syntax_tree/#{plugin}" }
print_width = DEFAULT_PRINT_WIDTH

while arguments.first&.start_with?("--")
case (argument = arguments.shift)
when /^--plugins=(.+)$/
# If there are any plugins specified on the command line, then load
# them by requiring them here. We do this by transforming something
# like
#
# stree format --plugins=haml template.haml
#
# into
#
# require "syntax_tree/haml"
#
$1.split(",").each { |plugin| require "syntax_tree/#{plugin}" }
when /^--print-width=(\d+)$/
# If there is a print width specified on the command line, then
# parse that out here and use it when formatting.
print_width = Integer($1)
else
warn("Unknown CLI option: #{argument}")
warn(HELP)
return 1
end
end

case name
Expand All @@ -271,19 +308,19 @@ def run(argv)
when "a", "ast"
AST.new
when "c", "check"
Check.new
Check.new(print_width: print_width)
when "debug"
Debug.new
Debug.new(print_width: print_width)
when "doc"
Doc.new
when "j", "json"
Json.new
when "m", "match"
Match.new
when "f", "format"
Format.new
Format.new(print_width: print_width)
when "w", "write"
Write.new
Write.new(print_width: print_width)
else
warn(HELP)
return 1
Expand Down
8 changes: 8 additions & 0 deletions test/cli_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ def test_check_unformatted
assert_includes(result.stderr, "expected")
end

def test_check_print_width
file = Tempfile.new(%w[test- .rb])
file.write("#{"a" * 40} + #{"b" * 40}\n")

result = run_cli("check", "--print-width=100", file: file)
assert_includes(result.stdio, "match")
end

def test_debug
result = run_cli("debug")
assert_includes(result.stdio, "idempotently")
Expand Down

0 comments on commit 509c29e

Please sign in to comment.