Skip to content

Commit

Permalink
fix: indenation of line-wrapped code [#171] (#7)
Browse files Browse the repository at this point in the history
* add failing test for #171

* dont assume lagging indentation is same as middle
  • Loading branch information
mbhall88 committed Feb 2, 2023
1 parent cbe88c7 commit f524574
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 5 deletions.
21 changes: 16 additions & 5 deletions snakefmt/formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
)
from snakefmt.types import TAB, TokenIterator

TAB_SIZE = len(TAB)
# This regex matches any number of consecutive strings; each can span multiple lines.
full_string_matcher = re.compile(
r"^\s*(\w?([\"']{3}.*?[\"']{3})|([\"']{1}.*?[\"']{1}))$", re.DOTALL | re.MULTILINE
Expand Down Expand Up @@ -170,7 +171,7 @@ def run_black_format_str(
string = f"if x:\n{textwrap.indent(string, TAB)}"

# reduce black target line length according to how indented the code is
current_line_length = (target_indent or 0) * len(TAB)
current_line_length = (target_indent or 0) * TAB_SIZE
black_mode = copy(self.black_mode)
black_mode.line_length = max(
0, black_mode.line_length - current_line_length + extra_spacing
Expand Down Expand Up @@ -219,8 +220,8 @@ def align_strings(self, string: str, target_indent: int) -> str:
indented += textwrap.indent(string[pos : match.start(1)], used_indent)
lagging_spaces = len(indented) - len(indented.rstrip(" "))
lagging_indent = (
TAB * int(lagging_spaces / len(TAB))
if lagging_spaces % len(TAB) == 0
TAB * int(lagging_spaces / TAB_SIZE)
if lagging_spaces % TAB_SIZE == 0
else ""
)
match_slice = string[match.start(1) : match.end(1)].replace("\t", TAB)
Expand All @@ -235,9 +236,19 @@ def align_strings(self, string: str, target_indent: int) -> str:
if is_multiline_string:
middle = "".join(all_lines[1:-1])
else:
mid = "".join(all_lines[1:-1])
dedent_mid = textwrap.dedent(mid)
lagging_indent_lvl = lagging_spaces // TAB_SIZE
if lagging_indent_lvl == 0:
required_indent_lvl = target_indent
else:
current_indent_lvl = (len(mid) - len(mid.lstrip())) // TAB_SIZE
required_indent_lvl = current_indent_lvl + target_indent

required_indent = TAB * required_indent_lvl
middle = textwrap.indent(
textwrap.dedent("".join(all_lines[1:-1])),
used_indent + lagging_indent,
dedent_mid,
required_indent,
)
indented += middle
if len(all_lines) > 1:
Expand Down
20 changes: 20 additions & 0 deletions tests/test_formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -1322,3 +1322,23 @@ def test_indented_block_with_functions_and_rule(self):
formatter = setup_formatter(snakecode)

assert formatter.get_formatted() == snakecode

def test_wrap_line_in_run_directive(self):
"""https://github.com/snakemake/snakefmt/issues/171"""
snakecode = (
"rule a:\n"
f"{TAB * 1}run:\n"
f"{TAB * 2}if x:\n"
f"{TAB * 3}for x in xs:\n"
f"{TAB * 4}if True:\n"
f'{TAB * 5}record_type, name, sequence, *__ = line.strip("\\n").split(\n'
f'{TAB * 6}"\\t", maxsplit=3\n'
f"{TAB * 5})\n"
f"{TAB * 5}new_line = (\n"
f'{TAB * 6}"\\t".join([record_type, name, "*", f"LN:i:{{len(sequence)}}"])\n' # noqa: E501
f'{TAB * 6}+ "\\n"\n'
f"{TAB * 5})\n"
)

formatter = setup_formatter(snakecode)
assert formatter.get_formatted() == snakecode

0 comments on commit f524574

Please sign in to comment.