Coding style

- Moved path_colored into lscolors.
  - Made lscolors a package.
  - Moved LS_COLORS.sh and LSCOLORS into lscolors.
- Moved fill3.join into termstr so that lscolors
  can depend on termstr only.
This commit is contained in:
Andrew Hamilton 2022-05-11 11:11:37 +10:00
parent fe42fd36d4
commit 388c59aefd
13 changed files with 85 additions and 70 deletions

View file

@ -35,6 +35,7 @@ import time
import docopt
import fill3
import fill3.terminal as terminal
import lscolors
import pygments.styles
import pyinotify
import termstr
@ -122,7 +123,7 @@ class Entry:
if self.highlighted is not None:
self.results[self.highlighted].is_highlighted = True
row_appearance = self.widget.appearance()
path = tools.path_colored(self.path)
path = lscolors.path_colored(self.path)
padding = " " * (self.last_width - len(self.results) + 1)
self.appearance_cache = [row_appearance[0] + padding + path]
if self.highlighted is not None:
@ -136,7 +137,7 @@ class Entry:
result_html, result_styles = result.as_html()
html_parts.append(result_html)
styles.update(result_styles)
path = tools.path_colored(self.path)
path = lscolors.path_colored(self.path)
padding = " " * (Entry.MAX_WIDTH - len(self.widget.widgets) + 1)
path_html, path_styles = termstr.TermStr(padding + path).as_html()
return "".join(html_parts) + path_html, styles.union(path_styles)
@ -560,7 +561,7 @@ class Log:
def log_message(self, message, timestamp=None, char_style=None):
if isinstance(message, list):
message = [part[1] if isinstance(part, tuple) else part for part in message]
message = fill3.join("", message)
message = termstr.join("", message)
if char_style is not None:
message = termstr.TermStr(message, char_style)
timestamp = time.strftime("%H:%M:%S", time.localtime()) if timestamp is None else timestamp
@ -587,12 +588,12 @@ def highlight_chars(str_, style, marker="*"):
parts = str_.split(marker)
highlighted_parts = [termstr.TermStr(part[0], style) + part[1:]
for part in parts[1:] if part != ""]
return fill3.join("", [parts[0]] + highlighted_parts)
return termstr.join("", [parts[0]] + highlighted_parts)
def get_status_help():
return fill3.join("\n", ["Statuses:"] + [" " + tools.STATUS_TO_TERMSTR[status] + " " + meaning
for status, meaning in tools.STATUS_MEANINGS])
return termstr.join("\n", ["Statuses:"] + [" " + tools.STATUS_TO_TERMSTR[status] + " " + meaning
for status, meaning in tools.STATUS_MEANINGS])
class Help:
@ -600,7 +601,7 @@ class Help:
def __init__(self, summary, screen):
self.summary = summary
self.screen = screen
help_text = fill3.join("\n", [__doc__, KEYS_DOC, get_status_help()])
help_text = termstr.join("\n", [__doc__, KEYS_DOC, get_status_help()])
self.view = fill3.View.from_widget(fill3.Text(help_text))
self.widget = fill3.Border(self.view, title="Help")
portal = self.view.portal
@ -777,7 +778,7 @@ class Screen:
"See option -e.")
else:
path = self._summary.get_selection().path
path_colored = tools.path_colored(path)
path_colored = lscolors.path_colored(path)
line_num = self._summary.get_selection().entry[0].scroll_position[1] + 1
self._log.log_message([in_green("Editing "), path_colored,
in_green(f" at line {line_num}")])
@ -801,7 +802,7 @@ class Screen:
def refresh(self):
selection = self._summary.get_selection()
tool_name = tools.tool_name_colored(selection.tool, selection.path)
path_colored = tools.path_colored(selection.path)
path_colored = lscolors.path_colored(selection.path)
self._log.log_message([in_green("Refreshing "), tool_name, in_green(" result of "),
path_colored, in_green("")])
self._summary.refresh_result(selection)
@ -829,7 +830,7 @@ class Screen:
def xdg_open(self):
path = self._summary.get_selection().path
path_colored = tools.path_colored(path)
path_colored = lscolors.path_colored(path)
self._log.log_message([in_green("Opening "), path_colored, in_green("")])
subprocess.Popen(["xdg-open", path], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@ -908,7 +909,7 @@ class Screen:
view.widget = widget.result
tool_name = tools.tool_name_colored(widget.tool, widget.path)
divider = " " + self._listing.top * 2 + " "
self._listing.title = (tools.path_colored(widget.path) + divider + tool_name + " " +
self._listing.title = (lscolors.path_colored(widget.path) + divider + tool_name + " " +
tools.STATUS_TO_TERMSTR[widget.status] + divider + "line " + str(y+1))
_STATUS_BAR = highlight_chars(" *help *quit *t*a*b:focus *turn *log *edit *next *sort"

View file

@ -67,13 +67,6 @@ STATUS_TO_TERMSTR = {status: termstr.TermStr(" ", termstr.CharStyle(bg_color=col
STATUS_TO_TERMSTR[Status.pending] = termstr.TermStr(".").fg_color(termstr.Color.grey_100)
def get_ls_color_codes():
with importlib.resources.open_text(eris, "LS_COLORS.sh") as lscolors_file:
codes = lscolors_file.readline().strip()[len("LS_COLORS='"):-len("';")]
return lscolors._parse_ls_colors(codes)
_LS_COLOR_CODES = get_ls_color_codes()
TIMEOUT = 60
@ -134,11 +127,11 @@ def _syntax_highlight(text, lexer, style):
token_style["underline"])
default_bg_color = _parse_rgb(style.background_color)
default_style = termstr.CharStyle(bg_color=default_bg_color)
text = fill3.join("", [termstr.TermStr(text, _char_style_for_token_type(
text = termstr.join("", [termstr.TermStr(text, _char_style_for_token_type(
token_type, default_bg_color, default_style))
for token_type, text in pygments.lex(text, lexer)])
text_widget = fill3.Text(text, pad_char=termstr.TermStr(" ").bg_color(default_bg_color))
return fill3.join("\n", text_widget.text)
return termstr.join("\n", text_widget.text)
def _syntax_highlight_using_path(text, path):
@ -205,8 +198,8 @@ def metadata(path):
else:
name, value = line
name = termstr.TermStr(name + ":").fg_color(termstr.Color.blue).ljust(16)
text.append(name + fill3.join("", value) + "\n")
return Status.ok, fill3.join("", text)
text.append(name + termstr.join("", value) + "\n")
return Status.ok, termstr.join("", text)
@deps(deps={"python3-pygments"}, url="http://pygments.org/")
@ -275,7 +268,7 @@ def mypy(path):
def _colorize_coverage_report(lines):
line_color = {"> ": termstr.Color.green, "! ": termstr.Color.grey_150, " ": None}
return fill3.join("", [termstr.TermStr(line).fg_color(line_color[line[:2]]) for line in lines])
return termstr.join("", [termstr.TermStr(line).fg_color(line_color[line[:2]]) for line in lines])
@deps(deps={"python3-coverage"}, url="https://coverage.readthedocs.io/")
@ -335,7 +328,7 @@ def _get_mccabe_line_score(line):
def _colorize_mccabe(text):
return fill3.join("", [
return termstr.join("", [
termstr.TermStr(line).fg_color(termstr.Color.yellow)
if _get_mccabe_line_score(line) > 10 else line
for line in text.splitlines(keepends=True)])
@ -398,7 +391,7 @@ def _image_to_text(image):
rows = [data[row_index*width:(row_index+1)*width] for row_index in range(image.height)]
if image.height % 2 == 1:
rows.append([None] * image.width)
return fill3.join("\n", [
return termstr.join("\n", [
termstr.TermStr(text, tuple(termstr.CharStyle(fg_color=top_pixel, bg_color=bottom_pixel)
for top_pixel, bottom_pixel in zip(rows[index], rows[index+1])))
for index in range(0, image.height, 2)])
@ -568,7 +561,7 @@ class Result:
async def run(self, log, runner):
tool_name = tool_name_colored(self.tool, self.path)
path = path_colored(self.path)
path = lscolors.path_colored(self.path)
log.log_message(["Running ", tool_name, " on ", path, ""])
self.set_status(Status.running)
fill3.APPEARANCE_CHANGED_EVENT.set()
@ -695,35 +688,10 @@ def run_tool_no_error(path, tool):
pygments.styles.get_style_by_name(os.environ["PYGMENT_STYLE"]))
def _charstyle_of_path(path):
color_code = lscolors.color_code_for_path(path, _LS_COLOR_CODES)
if color_code is None:
return termstr.CharStyle()
term_text = termstr.ESC + "[" + color_code + "m-"
return termstr.TermStr.from_term(term_text).style[0]
@functools.lru_cache(maxsize=100)
def path_colored(path):
char_style = _charstyle_of_path(path)
if path.startswith("./"):
path = path[2:]
dirname, basename = os.path.split(path)
if dirname == "":
return termstr.TermStr(basename, char_style)
else:
dirname = dirname + os.path.sep
dir_style = _charstyle_of_path(os.path.sep)
parts = [termstr.TermStr(part, dir_style) for part in dirname.split(os.path.sep)]
path_sep = termstr.TermStr(os.path.sep).fg_color(termstr.Color.grey_100)
dir_name = fill3.join(path_sep, parts)
return dir_name + termstr.TermStr(basename, char_style)
@functools.lru_cache(maxsize=100)
def tool_name_colored(tool, path):
char_style = (termstr.CharStyle(is_bold=True) if tool in generic_tools()
else _charstyle_of_path(path))
else lscolors._charstyle_of_path(path))
return termstr.TermStr(tool.__name__, char_style)

View file

@ -47,7 +47,7 @@ def make_listing_page(url_path):
result = index[(path, tool_name)]
tool = getattr(tools, tool_name)
tool_name_colored = tools.tool_name_colored(tool, path)
header = fill3.appearance_as_html([tools.path_colored(path) + " - " + tool_name_colored,
header = fill3.appearance_as_html([lscolors.path_colored(path) + " - " + tool_name_colored,
termstr.TermStr(" ").underline() * 100])
body = fill3.appearance_as_html(result.appearance())
return make_page(header + body, f"{path} - {tool_name}")

View file

@ -18,8 +18,8 @@ setup(name="eris",
license="Artistic 2.0",
python_requires=">=3.10.0",
packages=["eris"],
py_modules=["lscolors", "sorted_collection"],
package_data={"eris": ["LS_COLORS.sh", "tools.toml"]},
py_modules=["sorted_collection"],
package_data={"eris": ["tools.toml"]},
entry_points={"console_scripts":
["eris=eris.__main__:entry_point", "eris-worker=eris.worker:main",
"eris-webserver=eris.webserver:main", "pydoc_color=eris.pydoc_color:main"]},

View file

@ -10,6 +10,7 @@ import tempfile
import unittest
import fill3
import termstr
import golden
import eris.__main__ as __main__
@ -24,7 +25,7 @@ _DIMENSIONS = (100, 60)
def _widget_to_string(widget, dimensions=_DIMENSIONS):
appearance = (widget.appearance() if dimensions is None
else widget.appearance_for(dimensions))
return str(fill3.join("\n", appearance))
return str(termstr.join("\n", appearance))
def _touch(path):

View file

@ -7,7 +7,7 @@ import shutil
import unittest
import unittest.mock
import fill3
import termstr
import golden
import eris.tools as tools
@ -31,7 +31,7 @@ class ExecutablesTestCase(unittest.TestCase):
def widget_to_string(widget):
return str(fill3.join("\n", widget.appearance()))
return str(termstr.join("\n", widget.appearance()))
@contextlib.contextmanager

View file

@ -40,19 +40,10 @@ def appearance_dimensions(appearance):
return 0, 0
def join(seperator, parts):
if parts == []:
return ""
try:
return seperator.join(parts)
except TypeError:
return termstr.TermStr(seperator).join(parts)
def join_horizontal(appearances):
heights = set(len(appearance) for appearance in appearances)
assert len(heights) == 1, heights
return [join("", parts) for parts in zip(*appearances)]
return [termstr.join("", parts) for parts in zip(*appearances)]
def even_widths(column_widgets, width):

View file

@ -6,6 +6,7 @@ import unittest
import fill3
import fill3.terminal as terminal
import termstr
class WidgetTests(unittest.TestCase):
@ -14,7 +15,7 @@ class WidgetTests(unittest.TestCase):
TEXT_B = fill3.Text("B")
def assert_string(self, appearance, expected_string):
self.assertEqual(str(fill3.join("\n", appearance)), expected_string)
self.assertEqual(str(termstr.join("\n", appearance)), expected_string)
def test_rows_widget(self):
rows = fill3.Row([self.TEXT_A, self.TEXT_B])

View file

@ -3,11 +3,17 @@
"""Give coloring for file types as in the ls command."""
import functools
import importlib
import importlib.resources
import os
import os.path
import stat
import syslog
import lscolors
import termstr
__version__ = "v2022.04.30"
@ -127,3 +133,37 @@ def color_code_for_path(path, color_codes):
if extension is not None:
color_key = extension
return color_codes.get(color_key, None)
def get_ls_color_codes():
with importlib.resources.open_text(lscolors, "LS_COLORS.sh") as lscolors_file:
codes = lscolors_file.readline().strip()[len("LS_COLORS='"):-len("';")]
return _parse_ls_colors(codes)
_LS_COLOR_CODES = get_ls_color_codes()
def _charstyle_of_path(path):
color_code = color_code_for_path(path, _LS_COLOR_CODES)
if color_code is None:
return termstr.CharStyle()
term_text = termstr.ESC + "[" + color_code + "m-"
return termstr.TermStr.from_term(term_text).style[0]
@functools.lru_cache(maxsize=100)
def path_colored(path):
char_style = _charstyle_of_path(path)
if path.startswith("./"):
path = path[2:]
dirname, basename = os.path.split(path)
if dirname == "":
return termstr.TermStr(basename, char_style)
else:
dirname = dirname + os.path.sep
dir_style = _charstyle_of_path(os.path.sep)
parts = [termstr.TermStr(part, dir_style) for part in dirname.split(os.path.sep)]
path_sep = termstr.TermStr(os.path.sep).fg_color(termstr.Color.grey_100)
dir_name = termstr.join(path_sep, parts)
return dir_name + termstr.TermStr(basename, char_style)

View file

@ -1,12 +1,14 @@
#!/usr/bin/env python3.10
import os
try:
from setuptools import setup
except ImportError:
from distutils.core import setup
REPO_PATH = os.path.dirname(os.getcwd())
setup(name="lscolors",
version="v2022.04.30",
description=("Give coloring for file types as in the ls command."),
@ -14,4 +16,6 @@ setup(name="lscolors",
author="Andrew Hamilton",
author_email="and_hamilton@yahoo.com",
license="Artistic 2.0",
py_modules=["lscolors"])
packages=["lscolors"],
package_data={"lscolors": ["LS_COLORS.sh"]},
install_requires=[f"termstr @ file://{REPO_PATH}/termstr"])

View file

@ -177,6 +177,15 @@ def _pad_wide_chars(str_):
return str_ if len(padded_str) == len(str_) else padded_str
def join(seperator, parts):
if parts == []:
return ""
try:
return seperator.join(parts)
except TypeError:
return TermStr(seperator).join(parts)
class TermStr(collections.UserString):
def __init__(self, data, style=CharStyle()):