]>
git.madduck.net Git - etc/vim.git/blobdiff - src/black/trans.py
madduck's git repository
Every one of the projects in this repository is available at the canonical
URL git://git.madduck.net/madduck/pub/<projectpath> — see
each project's metadata for the exact URL.
All patches and comments are welcome. Please squash your changes to logical
commits before using git-format-patch and git-send-email to
patches@ git. madduck. net .
If you'd read over the Git project's submission guidelines and adhered to them,
I'd be especially grateful.
SSH access, as well as push access can be individually
arranged .
If you use my repositories frequently, consider adding the following
snippet to ~/.gitconfig and using the third clone URL listed for each
project:
[url "git://git.madduck.net/madduck/"]
insteadOf = madduck:
from black.comments import contains_pragma_comment
from black.lines import Line, append_leaves
from black.comments import contains_pragma_comment
from black.lines import Line, append_leaves
-from black.mode import Feature
+from black.mode import Feature, Mode
from black.nodes import (
CLOSING_BRACKETS,
OPENING_BRACKETS,
from black.nodes import (
CLOSING_BRACKETS,
OPENING_BRACKETS,
from black.rusty import Err, Ok, Result
from black.strings import (
assert_is_leaf_string,
from black.rusty import Err, Ok, Result
from black.strings import (
assert_is_leaf_string,
get_string_prefix,
has_triple_quotes,
normalize_string_quotes,
get_string_prefix,
has_triple_quotes,
normalize_string_quotes,
)
from blib2to3.pgen2 import token
from blib2to3.pytree import Leaf, Node
)
from blib2to3.pgen2 import token
from blib2to3.pytree import Leaf, Node
# types
T = TypeVar("T")
LN = Union[Leaf, Node]
# types
T = TypeVar("T")
LN = Union[Leaf, Node]
-Transformer = Callable[[Line, Collection[Feature]], Iterator[Line]]
+Transformer = Callable[[Line, Collection[Feature], Mode ], Iterator[Line]]
Index = int
NodeType = int
ParserState = int
Index = int
NodeType = int
ParserState = int
TResult = Result[T, CannotTransform] # (T)ransform Result
TMatchResult = TResult[List[Index]]
TResult = Result[T, CannotTransform] # (T)ransform Result
TMatchResult = TResult[List[Index]]
+SPLIT_SAFE_CHARS = frozenset(["\u3001", "\u3002", "\uff0c"]) # East Asian stops
+
def TErr(err_msg: str) -> Err[CannotTransform]:
"""(T)ransform Err
def TErr(err_msg: str) -> Err[CannotTransform]:
"""(T)ransform Err
return Err(cant_transform)
return Err(cant_transform)
-def hug_power_op(line: Line, features: Collection[Feature]) -> Iterator[Line]:
+def hug_power_op(
+ line: Line, features: Collection[Feature], mode: Mode
+) -> Iterator[Line]:
"""A transformer which normalizes spacing around power operators."""
# Performance optimization to avoid unnecessary Leaf clones and other ops.
"""A transformer which normalizes spacing around power operators."""
# Performance optimization to avoid unnecessary Leaf clones and other ops.
yield an CannotTransform after that point.)
"""
yield an CannotTransform after that point.)
"""
- def __call__(self, line: Line, _features: Collection[Feature]) -> Iterator[Line]:
+ def __call__(
+ self, line: Line, _features: Collection[Feature], _mode: Mode
+ ) -> Iterator[Line]:
"""
StringTransformer instances have a call signature that mirrors that of
the Transformer type.
"""
StringTransformer instances have a call signature that mirrors that of
the Transformer type.
# WMA4 the length of the inline comment.
offset += len(comment_leaf.value)
# WMA4 the length of the inline comment.
offset += len(comment_leaf.value)
- max_string_length = self.line_length - offset
+ max_string_length = count_chars_in_width(str(line), self.line_length - offset)
return max_string_length
@staticmethod
return max_string_length
@staticmethod
is_valid_index(string_idx + 1) and LL[string_idx + 1].type == token.COMMA
)
is_valid_index(string_idx + 1) and LL[string_idx + 1].type == token.COMMA
)
- def max_last_string() -> int:
+ def max_last_string_column () -> int:
- The max allowed length of the string value used for the last
- line we will construct.
+ The max allowed width of the string value used for the last
+ line we will construct. Note that this value means the width
+ rather than the number of characters (e.g., many East Asian
+ characters expand to two columns).
"""
result = self.line_length
result -= line.depth * 4
"""
result = self.line_length
result -= line.depth * 4
result -= string_op_leaves_length
return result
result -= string_op_leaves_length
return result
- # --- Calculate Max Break Index (for string value)
+ # --- Calculate Max Break Width (for string value)
# We start with the line length limit
# We start with the line length limit
- max_break_idx = self.line_length
+ max_break_width = self.line_length
# The last index of a string of length N is N-1.
# The last index of a string of length N is N-1.
# Leading whitespace is not present in the string value (e.g. Leaf.value).
# Leading whitespace is not present in the string value (e.g. Leaf.value).
- max_break_idx -= line.depth * 4
- if max_break_idx < 0:
+ max_break_width -= line.depth * 4
+ if max_break_width < 0:
yield TErr(
f"Unable to split {LL[string_idx].value} at such high of a line depth:"
f" {line.depth}"
yield TErr(
f"Unable to split {LL[string_idx].value} at such high of a line depth:"
f" {line.depth}"
# line limit.
use_custom_breakpoints = bool(
custom_splits
# line limit.
use_custom_breakpoints = bool(
custom_splits
- and all(csplit.break_idx <= max_break_idx for csplit in custom_splits)
+ and all(csplit.break_idx <= max_break_width for csplit in custom_splits)
)
# Temporary storage for the remaining chunk of the string line that
)
# Temporary storage for the remaining chunk of the string line that
if use_custom_breakpoints:
return len(custom_splits) > 1
else:
if use_custom_breakpoints:
return len(custom_splits) > 1
else:
- return len(rest_value) > max_last_string ()
+ return str_width(rest_value) > max_last_string_column ()
string_line_results: List[Ok[Line]] = []
while more_splits_should_be_made():
string_line_results: List[Ok[Line]] = []
while more_splits_should_be_made():
break_idx = csplit.break_idx
else:
# Algorithmic Split (automatic)
break_idx = csplit.break_idx
else:
# Algorithmic Split (automatic)
- max_bidx = max_break_idx - string_op_leaves_length
+ max_bidx = (
+ count_chars_in_width(rest_value, max_break_width)
+ - string_op_leaves_length
+ )
maybe_break_idx = self._get_break_idx(rest_value, max_bidx)
if maybe_break_idx is None:
# If we are unable to algorithmically determine a good split
maybe_break_idx = self._get_break_idx(rest_value, max_bidx)
if maybe_break_idx is None:
# If we are unable to algorithmically determine a good split
# Try to fit them all on the same line with the last substring...
if (
# Try to fit them all on the same line with the last substring...
if (
- len(temp_value) <= max_last_string ()
+ str_width(temp_value) <= max_last_string_column ()
or LL[string_idx + 1].type == token.COMMA
):
last_line.append(rest_leaf)
or LL[string_idx + 1].type == token.COMMA
):
last_line.append(rest_leaf)
section of this classes' docstring would be be met by returning @i.
"""
is_space = string[i] == " "
section of this classes' docstring would be be met by returning @i.
"""
is_space = string[i] == " "
+ is_split_safe = is_valid_index(i - 1) and string[i - 1] in SPLIT_SAFE_CHARS
is_not_escaped = True
j = i - 1
is_not_escaped = True
j = i - 1
and len(string[:i]) >= self.MIN_SUBSTR_SIZE
)
return (
and len(string[:i]) >= self.MIN_SUBSTR_SIZE
)
return (
+ (is_space or is_split_safe)
and is_not_escaped
and is_big_enough
and not breaks_unsplittable_expression(i)
and is_not_escaped
and is_big_enough
and not breaks_unsplittable_expression(i)
if string_idx is not None:
string_value = line.leaves[string_idx].value
if string_idx is not None:
string_value = line.leaves[string_idx].value
- # If the string has no spaces...
- if " " not in string_value:
+ # If the string has neither spaces nor East Asian stops...
+ if not any(
+ char == " " or char in SPLIT_SAFE_CHARS for char in string_value
+ ):
# And will still violate the line length limit when split...
# And will still violate the line length limit when split...
- max_string_leng th = self.line_length - ((line.depth + 1) * 4)
- if len(string_value) > max_string_leng th:
+ max_string_wid th = self.line_length - ((line.depth + 1) * 4)
+ if str_width(string_value) > max_string_wid th:
# And has no associated custom splits...
if not self.has_custom_splits(string_value):
# Then we should NOT put this string on its own line.
# And has no associated custom splits...
if not self.has_custom_splits(string_value):
# Then we should NOT put this string on its own line.