Skip to content
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

Add basic line length based formatting support #66

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
6470ebf
Add line length restrained printing utilities
gingermusketeer Sep 30, 2017
a794fbb
Fix tests for older versions of ruby
gingermusketeer Oct 1, 2017
d4558e1
Add more complex example and fix indent printing
gingermusketeer Oct 3, 2017
ca3a59a
Add initial prettier printing integration
gingermusketeer Nov 12, 2017
fbe2c42
Add doc mode helpers
gingermusketeer Nov 12, 2017
94ddb11
Return token from consume_token
gingermusketeer Nov 12, 2017
6b2895b
Allow print_width to be configured
gingermusketeer Nov 14, 2017
656636f
Fix more tests
gingermusketeer Nov 14, 2017
85e6165
Fix test for comment on first element
gingermusketeer Nov 14, 2017
8867e8b
Fix remaining trailing comma tests
gingermusketeer Nov 14, 2017
fdd6242
Fix simple method call spec
gingermusketeer Nov 14, 2017
a93cd49
Fix percent array literal test
gingermusketeer Nov 14, 2017
903e72a
Fix simple array specs
gingermusketeer Nov 15, 2017
df24550
Add support for star args
gingermusketeer Nov 15, 2017
6c90829
Fix more complex tests
gingermusketeer Nov 15, 2017
46cc5fd
Fix hash test
gingermusketeer Nov 15, 2017
8b015d6
Only use new args_add_star logic in doc mode
gingermusketeer Nov 15, 2017
130bc96
Fix comment on a newline after an array item
gingermusketeer Nov 15, 2017
4e52126
Handle strings in doc mode
gingermusketeer Nov 15, 2017
befd18d
Change specs to match new formatting
gingermusketeer Nov 16, 2017
5d50eb6
Fix nested array issue
gingermusketeer Nov 16, 2017
2d7b873
Add printer example for heredoc
gingermusketeer Nov 16, 2017
68113ea
Remove unneeded code
gingermusketeer Nov 16, 2017
de073df
Cleanup
gingermusketeer Nov 18, 2017
53e5eee
Address PR feedback
gingermusketeer Nov 22, 2017
d5bed76
Add example of nested array with brackets
gingermusketeer Nov 22, 2017
8fbe3ba
Merge branch 'master' into add-basic-line-length-based-formatting-sup…
gingermusketeer Nov 23, 2017
b57d338
Fix parens spec
gingermusketeer Nov 23, 2017
c607c78
Switch from CODE to RUBY for heredocs
gingermusketeer Nov 27, 2017
7944964
Cleanup unused code
gingermusketeer Nov 27, 2017
84f5f0a
Fix printing heredocs in printer
gingermusketeer Dec 2, 2017
5f97fdd
Fix heredoc handling for doc printer
gingermusketeer Dec 2, 2017
e71def6
Add new test cases and fix them
gingermusketeer Dec 2, 2017
711bfd5
Refactor to handle non doc handled nodes generically
gingermusketeer Dec 2, 2017
7fed281
Fix print_width config calculation
gingermusketeer Dec 2, 2017
e25138d
Format codebase
gingermusketeer Dec 2, 2017
8cc334d
Remove usage of squiggly heredocs
gingermusketeer Dec 2, 2017
ba42b5c
Add test for indentation issue
gingermusketeer Dec 2, 2017
c8ce87f
Merge branch 'master' into add-basic-line-length-based-formatting-sup…
gingermusketeer Dec 2, 2017
46ea2f4
Refactor literal elements method
gingermusketeer Dec 2, 2017
99901fd
Remove unneeded code
gingermusketeer Dec 2, 2017
660e797
Refactor comment handling
gingermusketeer Dec 2, 2017
7ff6caf
Code style tweaks
gingermusketeer Dec 2, 2017
c7028c2
Fix array literal bug
gingermusketeer Dec 2, 2017
4835c73
Handle percent array nested inside normal array
gingermusketeer Dec 2, 2017
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
2 changes: 2 additions & 0 deletions lib/rufo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,7 @@ def self.format(code, **options)
require_relative "rufo/command"
require_relative "rufo/dot_file"
require_relative "rufo/settings"
require_relative "rufo/doc_builder"
require_relative "rufo/doc_printer"
require_relative "rufo/formatter"
require_relative "rufo/version"
120 changes: 120 additions & 0 deletions lib/rufo/doc_builder.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
module Rufo
class DocBuilder
class InvalidDocError < StandardError; end

class << self

# Combine an array of items into a single string.
def concat(parts)
assert_docs(parts)
{
type: :concat, parts: parts,
}
end

# Increase level of indentation.
def indent(contents)
assert_doc(contents)
{
type: :indent, contents: contents,
}
end

# Increase indentation by a fixed number.
def align(n, contents)
assert_doc(contents)
{type: :align, contents: contents, n: n}
end

# Groups are items that the printer should try and fit onto a single line.
# If the group does not fit then it breaks instead.
def group(contents, opts = {})
assert_doc(contents)
{
type: :group,
contents: contents,
break: !!opts[:should_break],
expanded_states: opts[:expanded_states],
}
end

# Rather than breaking if the items do not fit this tries a different set
# of items.
def conditional_group(states, opts = {})
group(states.first, opts.merge(expanded_states: states))
end

# Alternative to group. This only breaks the required items rather then
# all items if they do not fit.
def fill(parts)
assert_docs(parts)

{type: :fill, parts: parts}
end

# Print first arg if the group breaks otherwise print the second.
def if_break(break_contents, flat_contents)
assert_doc(break_contents) unless break_contents.nil?
assert_doc(flat_contents) unless flat_contents.nil?

{type: :if_break, break_contents: break_contents, flat_contents: flat_contents}
end

# Append content to the end of a line. This gets placed just before a new line.
def line_suffix(contents)
assert_doc(contents)
{type: :line_suffix, contents: contents}
end

# Join list of items with a separator.
def join(sep, arr)
result = []
arr.each_with_index do |element, index|
unless index == 0
result << sep
end
result << element
end
concat(result)
end

def add_alignment_to_doc(doc, size, tab_width)
return doc unless size > 0
(size / tab_width).times { doc = indent(doc) }
doc = align(size % tab_width, doc)
align(-Float::INFINITY, doc)
end

private

def assert_docs(parts)
parts.each(&method(:assert_doc))
end

def assert_doc(val)
unless val.is_a?(String) || (val.is_a?(Hash) && val[:type].is_a?(Symbol))
raise InvalidDocError.new("Value #{val.inspect} is not a valid document")
end
end
end

# Use this to ensure that line suffixes do not move to the last line in group.
LINE_SUFFIX_BOUNDARY = {type: :line_suffix_boundary}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Constants at the bottom seems a little odd to me? Especially as they are referenced publically

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a little odd but the reason is that some of the constants utilize the methods defined further up. I thought that it might be best to keep them all together. Thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah that makes sense. I think this is fine then.

# Use this to force the parent to break
BREAK_PARENT = {type: :break_parent}
# If the content fits on one line the newline will be replaced with a space.
# Newlines are what triggers indentation to be added.
LINE = {type: :line}
# If the content fits on one line the newline will be replaced by nothing.
SOFT_LINE = {type: :line, soft: true}
# This newline is always included regardless of if the content fits on one
# line or not.
HARD_LINE = concat([{type: :line, hard: true}, BREAK_PARENT])
# This is a newline that is always included and does not cause the
# indentation to change subsequently.
LITERAL_LINE = concat([{type: :line, hard: true, literal: true}, BREAK_PARENT])

# This keeps track of the cursor in the document.
CURSOR = {type: :cursor, placeholder: :cursor}
end
end
Loading