Skip to content

Commit

Permalink
update the color scheme (#159)
Browse files Browse the repository at this point in the history
* don't highlight markup text

* don't change the color to white

* use black's new-ish color-scheme: blue for non-error stats

* only set the error message to "Oh no!" if there was an error

* also don't set the color to white in the diff highlighter

* print an empty line before the summary

* update the DiffHighlighter test to not expect bold white

* add a highlighter for reports

* get the highlighter to also add the bold for reformatted

* replace the statistics + formatting functions with a rich-aware class

* changelog
  • Loading branch information
keewis authored Oct 17, 2022
1 parent 5397b12 commit e79296d
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 60 deletions.
42 changes: 21 additions & 21 deletions blackdoc/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from .console import err, out
from .diff import unified_diff
from .files import collect_files
from .report import report_changes, report_possible_changes, statistics
from .report import Report

diff_highlighter = DiffHighlighter()

Expand Down Expand Up @@ -41,13 +41,15 @@ def format_and_overwrite(path, mode):
if new_content == content:
result = "unchanged"
else:
err.print(f"reformatted {path}", style="bold white")
err.print(f"reformatted {path}", style="bold", highlight=False)
result = "reformatted"

with open(path, "w", encoding=encoding, newline=newline) as f:
f.write(new_content)
except (black.InvalidInput, formats.InvalidFormatError) as e:
err.print(f"error: cannot format {path.absolute()}: {e}", style="red")
err.print(
f"error: cannot format {path.absolute()}: {e}", style="red", highlight=False
)
result = "error"

return result
Expand All @@ -65,7 +67,7 @@ def format_and_check(path, mode, diff=False, color=False):
if new_content == content:
result = "unchanged"
else:
err.print(f"would reformat {path}", style="bold white")
err.print(f"would reformat {path}", style="bold", highlight=False)

if diff:
diff_ = unified_diff(content, new_content, path)
Expand All @@ -79,15 +81,17 @@ def format_and_check(path, mode, diff=False, color=False):

result = "reformatted"
except (black.InvalidInput, formats.InvalidFormatError) as e:
err.print(f"error: cannot format {path.absolute()}: {e}", style="red")
err.print(
f"error: cannot format {path.absolute()}: {e}", style="red", highlight=False
)
result = "error"

return result


def process(args):
if not args.src:
err.print("No Path provided. Nothing to do :sleeping:", style="bold white")
err.print("No Path provided. Nothing to do :sleeping:", style="bold")
return 0

selected_formats = getattr(args, "formats", None)
Expand Down Expand Up @@ -153,7 +157,7 @@ def process(args):
if len(sources) == 0:
err.print(
"No files are present to be formatted. Nothing to do :sleeping:",
style="bold white",
style="bold",
)
return 0

Expand All @@ -178,29 +182,25 @@ def process(args):
changed_sources = {
source: action(source, mode, **action_kwargs) for source in sorted(sources)
}
n_reformatted, n_unchanged, n_error = statistics(changed_sources)

report_formatters = {
"inplace": report_changes,
"check": report_possible_changes,
}

report = report_formatters.get(args.action)(n_reformatted, n_unchanged, n_error)
conditional = args.action == "check"
report = Report.from_sources(changed_sources, conditional=conditional)

if n_error > 0:
if report.n_error > 0:
return_code = 123
elif args.action == "check" and n_reformatted > 0:
elif args.action == "check" and report.n_reformatted > 0:
return_code = 1
else:
return_code = 0

reformatted_message = "Oh no! :boom: :broken_heart: :boom:"
no_reformatting_message = "All done! :sparkles: :cake: :sparkles:"
error_message = "Oh no! :boom: :broken_heart: :boom:"
no_error_message = "All done! :sparkles: :cake: :sparkles:"
err.print()
err.print(
reformatted_message if return_code else no_reformatting_message,
style="bold white",
error_message if report.n_error > 0 else no_error_message,
style="bold",
)
err.print(report)
err.print(report, highlight=False)
return return_code


Expand Down
14 changes: 13 additions & 1 deletion blackdoc/colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

def line_style(lineno, line):
if line.startswith("+++") or line.startswith("---"):
yield lineno, (0, len(line)), "bold white"
yield lineno, (0, len(line)), "bold"
elif line.startswith("@@"):
yield lineno, (0, len(line)), "cyan"
elif line.startswith("+"):
Expand Down Expand Up @@ -52,3 +52,15 @@ def diff_styles(text):

for (start, end), style in diff_styles(text.plain):
text.stylize(style, start=start, end=end)


class FileHighlighter(Highlighter):
highlights = {
r"[0-9]+ files?(?!.*fail)": "blue",
r"^.+reformatted$": "bold",
r"^.+fail.+$": "red",
}

def highlight(self, text):
for highlight_re, style in self.highlights.items():
text.highlight_regex(highlight_re, style=style)
99 changes: 63 additions & 36 deletions blackdoc/report.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,8 @@
def report_changes(n_reformatted, n_unchanged, n_error):
def noun(n):
return "file" if n < 2 else "files"
from rich.text import Text

reports = []
if n_reformatted > 0:
reports.append(
f"[bold white]{n_reformatted} {noun(n_reformatted)} reformatted[/]",
)
from .colors import FileHighlighter

if n_unchanged > 0:
reports.append(f"[white]{n_unchanged} {noun(n_unchanged)} left unchanged[/]")

if n_error > 0:
reports.append(f"[red]{n_error} {noun(n_error)} fails to reformat[/]")

return ", ".join(reports) + "."


def report_possible_changes(n_reformatted, n_unchanged, n_error):
def noun(n):
return "file" if n < 2 else "files"

reports = []
if n_reformatted > 0:
reports.append(
f"[bold white]{n_reformatted} {noun(n_reformatted)} would be reformatted[/]",
)

if n_unchanged > 0:
reports.append(
f"[white]{n_unchanged} {noun(n_unchanged)} would be left unchanged[/]"
)

if n_error > 0:
reports.append(f"[red]{n_error} {noun(n_error)} would fail to reformat[/]")

return ", ".join(reports) + "."
highlighter = FileHighlighter()


def statistics(sources):
Expand All @@ -51,3 +18,63 @@ def statistics(sources):
raise RuntimeError(f"unknown results: {statistics.keys()}")

return n_reformatted, n_unchanged, n_error


def noun(n):
return "file" if n < 2 else "files"


class Report:
def __init__(self, n_reformatted, n_unchanged, n_error, conditional=False):
self.n_reformatted = n_reformatted
self.n_unchanged = n_unchanged
self.n_error = n_error

self.conditional = conditional

@classmethod
def from_sources(cls, sources, conditional=False):
n_reformatted, n_unchanged, n_error = statistics(sources)

return cls(n_reformatted, n_unchanged, n_error, conditional=conditional)

def __repr__(self):
params = [
f"{name}={getattr(self, name)}"
for name in ["n_reformatted", "n_unchanged", "n_error", "conditional"]
]
return f"Report({', '.join(params)})"

@property
def _reformatted_report(self):
if self.conditional:
return (
f"{self.n_reformatted} {noun(self.n_reformatted)} would be reformatted"
)
else:
return f"{self.n_reformatted} {noun(self.n_reformatted)} reformatted"

@property
def _unchanged_report(self):
if self.conditional:
return (
f"{self.n_unchanged} {noun(self.n_unchanged)} would be left unchanged"
)
else:
return f"{self.n_unchanged} {noun(self.n_unchanged)} left unchanged"

@property
def _error_report(self):
if self.conditional:
return f"{self.n_error} {noun(self.n_error)} would fail to reformat"
else:
return f"{self.n_error} {noun(self.n_error)} failed to reformat"

def __rich__(self):
raw_parts = [
self._reformatted_report,
self._unchanged_report,
self._error_report,
]
parts = [highlighter(part) for part in raw_parts]
return Text(", ").join(parts) + Text(".")
74 changes: 73 additions & 1 deletion blackdoc/tests/test_colors.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
+++ file2 time2
"""
),
[Span(0, 15, "bold white"), Span(16, 31, "bold white")],
[Span(0, 15, "bold"), Span(16, 31, "bold")],
id="header",
),
pytest.param(
Expand All @@ -51,3 +51,75 @@ def test_diff_highlighter(text, spans):

actual = diff_highlighter(text)
assert actual.spans == spans


@pytest.mark.parametrize(
["text", "spans"],
(
pytest.param(
"1 file would be reformatted",
[Span(0, 6, "blue"), Span(0, 27, "bold")],
id="single file-reformatted-conditional",
),
pytest.param(
"1 file reformatted",
[Span(0, 6, "blue"), Span(0, 18, "bold")],
id="single file-reformatted",
),
pytest.param(
"26 files would be reformatted",
[Span(0, 8, "blue"), Span(0, 29, "bold")],
id="multiple files-reformatted-conditional",
),
pytest.param(
"26 files reformatted",
[Span(0, 8, "blue"), Span(0, 20, "bold")],
id="multiple files-reformatted",
),
pytest.param(
"1 file would be left unchanged",
[Span(0, 6, "blue")],
id="single file-unchanged-conditional",
),
pytest.param(
"1 file left unchanged",
[Span(0, 6, "blue")],
id="single file-unchanged",
),
pytest.param(
"26 files would be left unchanged",
[Span(0, 8, "blue")],
id="multiple files-unchanged-conditional",
),
pytest.param(
"26 files left unchanged",
[Span(0, 8, "blue")],
id="multiple files-unchanged",
),
pytest.param(
"1 file would fail to reformat",
[Span(0, 29, "red")],
id="single file-error-conditional",
),
pytest.param(
"1 file failed to reformat",
[Span(0, 25, "red")],
id="single file-error",
),
pytest.param(
"15 files would fail to reformat",
[Span(0, 31, "red")],
id="multiple files-error-conditional",
),
pytest.param(
"15 files failed to reformat",
[Span(0, 27, "red")],
id="multiple files-error",
),
),
)
def test_file_highlighter(text, spans):
highlighter = colors.FileHighlighter()

actual = highlighter(text)
assert actual.spans == spans
2 changes: 1 addition & 1 deletion doc/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ v0.3.8 (*unreleased*)
- drop support for ``python=3.6`` (:pull:`153`)
- split chained statements into multiple ``doctest`` lines (:issue:`143`, :pull:`155`, :pull:`158`)
- replace the custom color formatting code with `rich <https://github.com/textualize/rich>`_
(:issue:`146`, :pull:`157`).
(:issue:`146`, :pull:`157`, :pull:`159`).

v0.3.7 (13 September 2022)
--------------------------
Expand Down

0 comments on commit e79296d

Please sign in to comment.