diff --git a/README.md b/README.md index 3a3803ec..fb1a49cd 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ It is built with only standard library dependencies. It additionally ships with - [json](#json) - [match](#match) - [write](#write) + - [Configuration](#configuration) - [Library](#library) - [SyntaxTree.read(filepath)](#syntaxtreereadfilepath) - [SyntaxTree.parse(source)](#syntaxtreeparsesource) @@ -231,6 +232,19 @@ To change the print width that you are writing with, specify the `--print-width` stree write --print-width=100 path/to/file.rb ``` +### Configuration + +Any of the above CLI commands can also read configuration options from a `.streerc` file in the directory where the commands are executed. + +This should be a text file with each argument on a separate line. + +```txt +--print-width=100 +--plugins=plugin/trailing_comma +``` + +If this file is present, it will _always_ be used for CLI commands. You can also pass options from the command line as in the examples above. The options in the `.streerc` file are passed to the CLI first, then the arguments from the command line. In the case of exclusive options (e.g. `--print-width`), this means that the command line options override what's in the config file. In the case of options that can take multiple inputs (e.g. `--plugins`), the effect is additive. That is, the plugins passed from the command line will be loaded _in addition to_ the plugins in the config file. + ## Library Syntax Tree can be used as a library to access the syntax tree underlying Ruby source code. diff --git a/lib/syntax_tree/cli.rb b/lib/syntax_tree/cli.rb index cad4fc35..fb2e4554 100644 --- a/lib/syntax_tree/cli.rb +++ b/lib/syntax_tree/cli.rb @@ -4,6 +4,8 @@ module SyntaxTree # Syntax Tree ships with the `stree` CLI, which can be used to inspect and # manipulate Ruby code. This module is responsible for powering that CLI. module CLI + CONFIG_FILE = ".streerc" + # A utility wrapper around colored strings in the output. class Color attr_reader :value, :code @@ -269,6 +271,11 @@ def run(argv) name, *arguments = argv print_width = DEFAULT_PRINT_WIDTH + config_file = File.join(Dir.pwd, CONFIG_FILE) + if File.readable?(config_file) + arguments.unshift(*File.readlines(config_file, chomp: true)) + end + while arguments.first&.start_with?("--") case (argument = arguments.shift) when /^--plugins=(.+)$/ diff --git a/test/cli_test.rb b/test/cli_test.rb index 31e4b7e2..9bc237fb 100644 --- a/test/cli_test.rb +++ b/test/cli_test.rb @@ -180,6 +180,77 @@ def test_language_server $stdout = prev_stdout end + def test_config_file + config_file = File.join(Dir.pwd, SyntaxTree::CLI::CONFIG_FILE) + config = <<~TXT + --print-width=100 + --plugins=plugin + TXT + File.write(config_file, config) + + Dir.mktmpdir do |directory| + Dir.mkdir(File.join(directory, "syntax_tree")) + $:.unshift(directory) + + File.write( + File.join(directory, "syntax_tree", "plugin.rb"), + "puts 'Hello, world!'" + ) + + file = Tempfile.new(%w[test- .rb]) + contents = "#{"a" * 40} + #{"b" * 40}\n" + file.write(contents) + + result = run_cli("format", file: file) + assert_equal("Hello, world!\n#{contents}", result.stdio) + end + ensure + FileUtils.rm(config_file) + end + + def test_print_width_args_with_config_file + config_file = File.join(Dir.pwd, SyntaxTree::CLI::CONFIG_FILE) + File.write(config_file, "--print-width=100") + + contents = "#{"a" * 40} + #{"b" * 40}\n" + + file = Tempfile.new(%w[test- .rb]) + file.write(contents) + result = run_cli("check", file: file) + assert_includes(result.stdio, "match") + + file = Tempfile.new(%w[test- .rb]) + file.write(contents) + result = run_cli("check", "--print-width=82", file: file) + assert_includes(result.stderr, "expected") + ensure + FileUtils.rm(config_file) + end + + def test_plugin_args_with_config_file + config_file = File.join(Dir.pwd, SyntaxTree::CLI::CONFIG_FILE) + File.write(config_file, "--plugins=hello_plugin") + + Dir.mktmpdir do |directory| + Dir.mkdir(File.join(directory, "syntax_tree")) + $:.unshift(directory) + + File.write( + File.join(directory, "syntax_tree", "hello_plugin.rb"), + "puts 'Hello, world!'" + ) + File.write( + File.join(directory, "syntax_tree", "bye_plugin.rb"), + "puts 'Bye, world!'" + ) + + result = run_cli("format", "--plugins=bye_plugin") + assert_equal("Hello, world!\nBye, world!\ntest\n", result.stdio) + end + ensure + FileUtils.rm(config_file) + end + private Result = Struct.new(:status, :stdio, :stderr, keyword_init: true)