Skip to content

Commit

Permalink
fix: improve handling of indenting in shell directive [#186]
Browse files Browse the repository at this point in the history
  • Loading branch information
mbhall88 committed Jan 6, 2024
1 parent 022d6ab commit 105e856
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 8 deletions.
22 changes: 14 additions & 8 deletions snakefmt/formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,26 +219,27 @@ def align_strings(self, string: str, target_indent: int) -> str:
for match in re.finditer(full_string_matcher, string):
indented += textwrap.indent(string[pos : match.start(1)], used_indent)
lagging_spaces = len(indented) - len(indented.rstrip(" "))
lagging_indent = (
TAB * int(lagging_spaces / TAB_SIZE)
if lagging_spaces % TAB_SIZE == 0
else ""
)
lagging_indent_lvl = lagging_spaces // TAB_SIZE
match_slice = string[match.start(1) : match.end(1)].replace("\t", TAB)
all_lines = match_slice.splitlines(keepends=True)
first = textwrap.indent(textwrap.dedent(all_lines[0]), used_indent)
indented += first

is_multiline_string = re.match(
r"[bfru]?\"\"\"|'''", first.lstrip(), flags=re.IGNORECASE
)
indented += first
if not is_multiline_string:
# this check if string is a single-quoted multiline string
# e.g. https://github.com/snakemake/snakefmt/issues/121
is_multiline_string = "\\\n" in first

if len(all_lines) > 2:
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:
Expand All @@ -251,12 +252,17 @@ def align_strings(self, string: str, target_indent: int) -> str:
required_indent,
)
indented += middle

if len(all_lines) > 1:
if is_multiline_string:
last = all_lines[-1]
else:
leading_spaces = len(all_lines[-1]) - len(
textwrap.dedent(all_lines[-1])
)
leading_indent = leading_spaces // TAB_SIZE * TAB
last = textwrap.indent(
textwrap.dedent(all_lines[-1]), used_indent + lagging_indent
textwrap.dedent(all_lines[-1]), used_indent + leading_indent
)
indented += last
pos = match.end()
Expand Down
40 changes: 40 additions & 0 deletions tests/test_formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -1358,3 +1358,43 @@ def test_wrap_line_in_run_directive(self):

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

def test_shell_indention_long_line(self):
"""https://github.com/snakemake/snakefmt/issues/186
test this rule
rule test1:
input:
"...",
output:
"...",
shell:
myfunc(
"param1",
[
"item1",
f"very_long_item2_{very_long_function(other_param)}"
if some_very_long_condition
else "",
],
)
"""
snakecode = (
"rule test1:\n"
f"{TAB * 1}input:\n"
f'{TAB * 2}"...",\n'
f"{TAB * 1}output:\n"
f'{TAB * 2}"...",\n'
f"{TAB * 1}shell:\n"
f"{TAB * 2}myfunc(\n"
f'{TAB * 3}"param1",\n'
f"{TAB * 3}[\n"
f'{TAB * 4}"item1",\n'
f'{TAB * 4}f"very_long_item2_{{very_long_function(other_param)}}"\n'
f"{TAB * 4}if some_very_long_condition\n"
f'{TAB * 4}else "",\n'
f"{TAB * 3}],\n"
f"{TAB * 2})\n"
)
formatter = setup_formatter(snakecode)
assert formatter.get_formatted() == snakecode

0 comments on commit 105e856

Please sign in to comment.