Skip to content

Allow specifying --print-width in the CLI #115

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
107 changes: 74 additions & 33 deletions lib/syntax_tree/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,17 @@ 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)
if source != item.handler.format(source, print_width)
raise UnformattedError
end
rescue StandardError
warn("[#{Color.yellow("warn")}] #{item.filepath}")
raise
Expand All @@ -114,13 +122,21 @@ 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)
if formatted != handler.format(formatted, print_width)
raise NonIdempotentFormatError
end
rescue StandardError
warn(warning)
raise
Expand Down Expand Up @@ -148,8 +164,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 +195,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 +222,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 +312,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