Skip to content

Commit

Permalink
Add a --use-tabs argument to use tabs instead of spaces
Browse files Browse the repository at this point in the history
  • Loading branch information
jleclanche authored and sciyoshi committed Sep 22, 2022
1 parent ba3c131 commit 6794353
Show file tree
Hide file tree
Showing 9 changed files with 369 additions and 9 deletions.
9 changes: 9 additions & 0 deletions src/black/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,13 @@ def validate_regex(
" functionality in the next major release."
),
)
@click.option(
"--use-tabs",
is_flag=True,
help=(
"Use tabs instead of spaces for indentation. Tabs are always equal to 4 spaces."
),
)
@click.option(
"--check",
is_flag=True,
Expand Down Expand Up @@ -432,6 +439,7 @@ def main( # noqa: C901
skip_magic_trailing_comma: bool,
experimental_string_processing: bool,
preview: bool,
use_tabs: bool,
quiet: bool,
verbose: bool,
required_version: Optional[str],
Expand Down Expand Up @@ -533,6 +541,7 @@ def main( # noqa: C901
experimental_string_processing=experimental_string_processing,
preview=preview,
python_cell_magics=set(python_cell_magics),
use_tabs=use_tabs,
)

if code is not None:
Expand Down
8 changes: 5 additions & 3 deletions src/black/linegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,10 +353,11 @@ def visit_STRING(self, leaf: Leaf) -> Iterator[Line]:
quote_len = 1 if docstring[1] != quote_char else 3
docstring = docstring[quote_len:-quote_len]
docstring_started_empty = not docstring
indent = " " * 4 * self.current_line.depth
indent_style = " " * 4 if not self.mode.use_tabs else "\t"
indent = indent_style * self.current_line.depth

if is_multiline_string(leaf):
docstring = fix_docstring(docstring, indent)
docstring = fix_docstring(docstring, indent, not self.mode.use_tabs)
else:
docstring = docstring.strip()

Expand Down Expand Up @@ -453,7 +454,8 @@ def transform_line(
yield line
return

line_str = line_to_string(line)
# Force spaces to ensure len(line) is correct
line_str = line.render(force_spaces=True).strip("\n")

ll = mode.line_length
sn = mode.string_normalization
Expand Down
14 changes: 10 additions & 4 deletions src/black/lines.py
Original file line number Diff line number Diff line change
Expand Up @@ -428,11 +428,15 @@ def clone(self) -> "Line":
)

def __str__(self) -> str:
return self.render()

def render(self, force_spaces: bool = False) -> str:
"""Render the line."""
if not self:
return "\n"

indent = " " * self.depth
indent_style = " " if force_spaces or not self.mode.use_tabs else "\t"
indent = indent_style * self.depth
leaves = iter(self.leaves)
first = next(leaves)
res = f"{first.prefix}{indent}{first.value}"
Expand Down Expand Up @@ -650,7 +654,9 @@ def is_line_short_enough(line: Line, *, line_length: int, line_str: str = "") ->
Uses the provided `line_str` rendering, if any, otherwise computes a new one.
"""
if not line_str:
line_str = line_to_string(line)
line_str = line_to_string(line, force_spaces=True)
else:
line_str = line_str.expandtabs(tabsize=4)
return (
len(line_str) <= line_length
and "\n" not in line_str # multiline strings
Expand Down Expand Up @@ -803,9 +809,9 @@ def _can_omit_closing_paren(line: Line, *, last: Leaf, line_length: int) -> bool
return False


def line_to_string(line: Line) -> str:
def line_to_string(line: Line, force_spaces: bool = False) -> str:
"""Returns the string representation of @line.
WARNING: This is known to be computationally expensive.
"""
return str(line).strip("\n")
return line.render(force_spaces=force_spaces).strip("\n")
2 changes: 2 additions & 0 deletions src/black/mode.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ class Mode:
experimental_string_processing: bool = False
python_cell_magics: Set[str] = field(default_factory=set)
preview: bool = False
use_tabs: bool = False

def __post_init__(self) -> None:
if self.experimental_string_processing:
Expand Down Expand Up @@ -212,5 +213,6 @@ def get_cache_key(self) -> str:
str(int(self.experimental_string_processing)),
str(int(self.preview)),
sha256((",".join(sorted(self.python_cell_magics))).encode()).hexdigest(),
str(int(self.use_tabs)),
]
return ".".join(parts)
7 changes: 5 additions & 2 deletions src/black/strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,14 @@ def lines_with_leading_tabs_expanded(s: str) -> List[str]:
return lines


def fix_docstring(docstring: str, prefix: str) -> str:
def fix_docstring(docstring: str, prefix: str, expand_leading_tabs: bool) -> str:
# https://www.python.org/dev/peps/pep-0257/#handling-docstring-indentation
if not docstring:
return ""
lines = lines_with_leading_tabs_expanded(docstring)
if expand_leading_tabs:
lines = lines_with_leading_tabs_expanded(docstring)
else:
lines = docstring.splitlines()
# Determine minimum indentation (first line doesn't count):
indent = sys.maxsize
for line in lines[1:]:
Expand Down
Loading

0 comments on commit 6794353

Please sign in to comment.