.format replaced by f-strings
This commit is contained in:
@@ -32,7 +32,7 @@ class Region:
|
||||
return (self.a, self.b) == (other.a, other.b)
|
||||
|
||||
def __repr__(self):
|
||||
return "Region({}, {})".format(self.a, self.b)
|
||||
return f"Region({self.a}, {self.b})"
|
||||
|
||||
|
||||
class Settings(dict):
|
||||
@@ -240,7 +240,13 @@ def find_syntax_for_file(path, first_line=""):
|
||||
|
||||
|
||||
def ui_info():
|
||||
return {"system": {"style": "dark"}, "color_scheme": {"value": "Mariana.sublime-color-scheme", "resolved_value": "Packages/Color Scheme - Default/Mariana.sublime-color-scheme"}}
|
||||
return {
|
||||
"system": {"style": "dark"},
|
||||
"color_scheme": {
|
||||
"value": "Mariana.sublime-color-scheme",
|
||||
"resolved_value": "Packages/Color Scheme - Default/Mariana.sublime-color-scheme",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def decode_value(text):
|
||||
|
||||
@@ -11,7 +11,7 @@ def change(path, status="M"):
|
||||
|
||||
def flagged(*flags):
|
||||
"""f0.py, f1.py ... with the given staged flags"""
|
||||
return [git.FileChange("f{}.py".format(i), "M", flag, 1, 1, None) for i, flag in enumerate(flags)]
|
||||
return [git.FileChange(f"f{i}.py", "M", flag, 1, 1, None) for i, flag in enumerate(flags)]
|
||||
|
||||
|
||||
def option(monkeypatch, name, value):
|
||||
@@ -28,7 +28,7 @@ def at_change(blocks, row):
|
||||
view = sublime.View()
|
||||
st = state.ViewState("/repo")
|
||||
st.blocks = blocks
|
||||
view.text = "\n" + "\n".join("l{}".format(i) for i in range(20))
|
||||
view.text = "\n" + "\n".join(f"l{i}" for i in range(20))
|
||||
view.sel().add(sublime.Region(commands.render.index_point(view, row)))
|
||||
return view, st
|
||||
|
||||
|
||||
@@ -133,9 +133,9 @@ def test_help_popup_lists_every_key():
|
||||
|
||||
assert view.is_popup_visible()
|
||||
for group in ("Navigate", "Panels", "Actions", "View"):
|
||||
assert ">{}<".format(group) in html
|
||||
assert f">{group}<" in html
|
||||
for keys in ("] [", "n p", "o ⏎", "j k", "f", "c", "s", "u", "d", "C", "m", "r", "?", "esc"):
|
||||
assert ">{}<".format(keys) in html
|
||||
assert f">{keys}<" in html
|
||||
assert "next / previous change" in html and "open the real file at this line" in html
|
||||
# working-tree mode: nothing dimmed, every single-action row is a link
|
||||
assert 'class="dim"' not in html and "uncommitted only" not in html
|
||||
@@ -222,7 +222,7 @@ def test_minihtml_stylesheets_reject_unsupported_selectors():
|
||||
for rule in css.split("}"):
|
||||
head = rule.split("{")[0].strip()
|
||||
for selector in filter(None, (s.strip() for s in head.split(","))):
|
||||
assert not unsupported.search(selector), "{}: {}".format(name, selector)
|
||||
assert not unsupported.search(selector), f"{name}: {selector}"
|
||||
|
||||
|
||||
# --- header summary line ----------------------------------------------------
|
||||
@@ -238,7 +238,26 @@ def test_summary_counts_staged_and_unstaged_files():
|
||||
git.FileChange("c.py", "?", False, 1, 0, None),
|
||||
]
|
||||
render.render(view, st)
|
||||
assert '<div class="summary">1 staged, 2 unstaged</div>' in header(view)
|
||||
summary = header(view).split('<div class="summary">')[1].split("</div>")[0]
|
||||
|
||||
# the untracked file's whole content counts as insertions, the way git.changed_files records it
|
||||
assert summary.startswith("1 staged, 2 unstaged · ")
|
||||
assert '<span class="del">-2</span>' in summary and '<span class="ins">+3</span>' in summary
|
||||
|
||||
|
||||
def test_summary_totals_skip_binary_files_but_still_count_them():
|
||||
view = sublime.View()
|
||||
render.init_view(view)
|
||||
st = make_state()
|
||||
st.files = [
|
||||
git.FileChange("a.py", "M", False, 4, 1, None),
|
||||
git.FileChange("logo.png", "M", False, None, None, None), # binary: no counts, still a file
|
||||
]
|
||||
render.render(view, st)
|
||||
summary = header(view).split('<div class="summary">')[1].split("</div>")[0]
|
||||
|
||||
assert summary.startswith("0 staged, 2 unstaged · ")
|
||||
assert '<span class="del">-1</span>' in summary and '<span class="ins">+4</span>' in summary
|
||||
|
||||
|
||||
def test_summary_totals_a_commit_and_owns_the_date():
|
||||
|
||||
@@ -120,7 +120,7 @@ def file_items(files):
|
||||
if None in (change.insertions, change.deletions):
|
||||
annotation = "binary"
|
||||
else:
|
||||
annotation = "-{} +{}".format(change.deletions, change.insertions)
|
||||
annotation = f"-{change.deletions} +{change.insertions}"
|
||||
items.append(sublime.QuickPanelItem(change.path, details, annotation, kind))
|
||||
return items
|
||||
|
||||
@@ -132,14 +132,12 @@ def commit_items(commits):
|
||||
annotation = c.short
|
||||
if c.files is not None:
|
||||
# merges and empty commits have no diffstat, so they show the hash alone
|
||||
annotation = "{} changed -{} +{} {}".format(
|
||||
file_count(c.files), c.deletions, c.insertions, c.short
|
||||
)
|
||||
annotation = f"{file_count(c.files)} changed -{c.deletions} +{c.insertions} {c.short}"
|
||||
subject = c.subject or "(no subject)"
|
||||
budget = max(COMMIT_ROW_WIDTH - len(annotation), MIN_SUBJECT_WIDTH)
|
||||
if len(subject) > budget:
|
||||
subject = subject[: budget - 2] + ".."
|
||||
items.append(sublime.QuickPanelItem(subject, "{} · {}".format(c.author, c.date), annotation, COMMIT_KIND))
|
||||
items.append(sublime.QuickPanelItem(subject, f"{c.author} · {c.date}", annotation, COMMIT_KIND))
|
||||
return items
|
||||
|
||||
|
||||
@@ -192,7 +190,7 @@ def refresh_listing(view, st, message=None, pick=None):
|
||||
return
|
||||
st.files = files
|
||||
if not files:
|
||||
render.render_message(view, st, "No uncommitted changes in {}".format(st.repo))
|
||||
render.render_message(view, st, f"No uncommitted changes in {st.repo}")
|
||||
return
|
||||
index = state.find_change(files, path)
|
||||
if index < 0:
|
||||
@@ -227,10 +225,10 @@ class VdiffFilesCommand(sublime_plugin.WindowCommand):
|
||||
return
|
||||
kept = st.enter()
|
||||
if not files:
|
||||
render.render_message(view, st, "No uncommitted changes in {}".format(st.repo))
|
||||
render.render_message(view, st, f"No uncommitted changes in {st.repo}")
|
||||
status("no uncommitted changes")
|
||||
return
|
||||
placeholder = "Changed files in {}".format(os.path.basename(st.repo))
|
||||
placeholder = f"Changed files in {os.path.basename(st.repo)}"
|
||||
show_files_panel(window, view, st, files, kept, placeholder=placeholder)
|
||||
|
||||
run_async(lambda: git.changed_files(st.repo), done)
|
||||
@@ -281,13 +279,13 @@ class VdiffCommitsCommand(sublime_plugin.WindowCommand):
|
||||
info, files = result
|
||||
kept = st.enter(info.sha, info)
|
||||
if not files:
|
||||
render.render_message(view, st, "Commit {} touches no files".format(info.short))
|
||||
render.render_message(view, st, f"Commit {info.short} touches no files")
|
||||
return
|
||||
|
||||
def back():
|
||||
window.run_command("vdiff_commits", {"selected": index})
|
||||
|
||||
placeholder = "{} · {}".format(info.short, info.subject)
|
||||
placeholder = f"{info.short} · {info.subject}"
|
||||
on_cancel = back if index is not None else None
|
||||
show_files_panel(window, view, st, files, kept, on_cancel=on_cancel, placeholder=placeholder)
|
||||
|
||||
@@ -321,14 +319,14 @@ def _git_action(verb, done_verb, operation, confirm=None, pick=None):
|
||||
|
||||
def act(view, window, st):
|
||||
if st.in_commit or st.change is None:
|
||||
status("{} works on uncommitted changes only".format(verb))
|
||||
status(f"{verb} works on uncommitted changes only")
|
||||
return
|
||||
change = st.change
|
||||
if confirm is not None and not confirm(change):
|
||||
return
|
||||
run_async(
|
||||
lambda: operation(st.repo, change),
|
||||
lambda _: refresh_listing(view, st, "{} {}".format(done_verb, change.path), pick=pick),
|
||||
lambda _: refresh_listing(view, st, f"{done_verb} {change.path}", pick=pick),
|
||||
)
|
||||
|
||||
return act
|
||||
@@ -338,10 +336,11 @@ def _confirm_discard(change):
|
||||
if not settings().get("confirm_discard", True):
|
||||
return True
|
||||
if change.status == "?":
|
||||
message = "Delete the untracked file {}?\n\nThis cannot be undone.".format(change.path)
|
||||
message = f"Delete the untracked file {change.path}?\n\nThis cannot be undone."
|
||||
else:
|
||||
message = "Discard all changes to {}?\n\nThe file goes back to its last committed version. This cannot be undone.".format(
|
||||
change.path
|
||||
message = (
|
||||
f"Discard all changes to {change.path}?\n\n"
|
||||
"The file goes back to its last committed version. This cannot be undone."
|
||||
)
|
||||
return sublime.ok_cancel_dialog(message, "Discard")
|
||||
|
||||
@@ -378,10 +377,10 @@ def _act_open(view, window, st):
|
||||
return
|
||||
path = os.path.join(st.repo, st.change.path)
|
||||
if not os.path.exists(path):
|
||||
status("{} does not exist in the working tree".format(st.change.path))
|
||||
status(f"{st.change.path} does not exist in the working tree")
|
||||
return
|
||||
line = parse.line_for_open(st.lines, render.caret_index(view))
|
||||
window.open_file("{}:{}".format(path, line), sublime.ENCODED_POSITION)
|
||||
window.open_file(f"{path}:{line}", sublime.ENCODED_POSITION)
|
||||
|
||||
|
||||
def _step_file(delta):
|
||||
@@ -442,7 +441,7 @@ def _act_commit(view, window, st):
|
||||
return
|
||||
run_async(
|
||||
lambda: git.commit(st.repo, message),
|
||||
lambda _: refresh_listing(view, st, "committed {}".format(file_count(len(staged)))),
|
||||
lambda _: refresh_listing(view, st, f"committed {file_count(len(staged))}"),
|
||||
)
|
||||
|
||||
window.show_input_panel("Commit message", "", on_done, None, None)
|
||||
@@ -468,7 +467,7 @@ def _act_amend(view, window, st):
|
||||
return
|
||||
done = "amended the last commit"
|
||||
if staged:
|
||||
done += " with {}".format(file_count(len(staged)))
|
||||
done += f" with {file_count(len(staged))}"
|
||||
run_async(
|
||||
# nothing staged makes this a pure reword, which git refuses on an empty commit
|
||||
lambda: git.amend(st.repo, text + newline + body, allow_empty=not staged),
|
||||
@@ -520,7 +519,7 @@ class VdiffActionCommand(sublime_plugin.TextCommand):
|
||||
def run(self, edit, action):
|
||||
act = ACTIONS.get(action)
|
||||
if act is None:
|
||||
status("unknown action {}".format(action))
|
||||
status(f"unknown action {action}")
|
||||
return
|
||||
st = state.get(self.view) or restore_view(self.view)
|
||||
act(self.view, self.view.window(), st)
|
||||
@@ -558,7 +557,7 @@ def restore_view(view):
|
||||
if index >= 0:
|
||||
show_file(view, st, files[index])
|
||||
else:
|
||||
render.render_message(view, st, "{} has no uncommitted changes any more".format(path))
|
||||
render.render_message(view, st, f"{path} has no uncommitted changes any more")
|
||||
|
||||
run_async(lambda: git.changed_files(repo), done)
|
||||
return st
|
||||
|
||||
10
vdiff/git.py
10
vdiff/git.py
@@ -44,15 +44,13 @@ class GitError(Exception):
|
||||
self.stderr = stderr
|
||||
self.code = code
|
||||
first = stderr.strip().splitlines()
|
||||
super().__init__(first[0] if first else "git exited with {}".format(code))
|
||||
super().__init__(first[0] if first else f"git exited with {code}")
|
||||
|
||||
|
||||
def run(repo, args, ok_codes=(0,)):
|
||||
"""Run git in `repo`, return stdout as text"""
|
||||
cmd = [GIT_BINARY, "-c", "core.quotepath=off", "--no-pager"] + list(args)
|
||||
proc = subprocess.run(
|
||||
cmd, cwd=repo, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf-8", errors="replace"
|
||||
)
|
||||
proc = subprocess.run(cmd, cwd=repo, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf-8", errors="replace")
|
||||
if proc.returncode not in ok_codes:
|
||||
raise GitError(proc.stderr, proc.returncode)
|
||||
return proc.stdout
|
||||
@@ -201,7 +199,7 @@ def recent_commits(repo, count):
|
||||
def commit_with_files(repo, sha):
|
||||
"""(CommitInfo, [FileChange]) of one commit vs its first parent, files sorted by path; two git calls"""
|
||||
show = ["show", "--first-parent", "-m", "-z"]
|
||||
text = run(repo, show + ["--format={}%x00".format(_INFO_FORMAT), _DATE_FORMAT, "--name-status", sha])
|
||||
text = run(repo, show + [f"--format={_INFO_FORMAT}%x00", _DATE_FORMAT, "--name-status", sha])
|
||||
# git terminates the header with its own NUL and a newline before the file list
|
||||
info_text, _, files_text = text.partition("\0")
|
||||
files_text = files_text.lstrip("\0\n")
|
||||
@@ -222,7 +220,7 @@ def commit_with_files(repo, sha):
|
||||
def _in_tree(repo, ref, path):
|
||||
"""Whether `path` exists in the tree of `ref`"""
|
||||
try:
|
||||
run(repo, ["cat-file", "-e", "{}:{}".format(ref, path)])
|
||||
run(repo, ["cat-file", "-e", f"{ref}:{path}"])
|
||||
return True
|
||||
except GitError:
|
||||
return False
|
||||
|
||||
120
vdiff/render.py
120
vdiff/render.py
@@ -60,33 +60,49 @@ FALLBACK_RULES = [
|
||||
Key = namedtuple("Key", "keys label short actions")
|
||||
|
||||
KEY_GROUPS = [
|
||||
("Navigate", True, [
|
||||
Key("] [", "next / previous change (wraps)", "change", ("next_change", "prev_change")),
|
||||
Key("n p", "next / previous file (wraps)", "file", ("next_file", "prev_file")),
|
||||
Key("o \u23ce", "open the real file at this line", "open", ("open",)),
|
||||
Key("j k", "down / up one line (vim)", "", ("line_down", "line_up")),
|
||||
]),
|
||||
("Panels", True, [
|
||||
Key("f", "changed files", "files", ("files",)),
|
||||
Key("c", "recent commits", "commits", ("commits",)),
|
||||
]),
|
||||
("Actions", False, [
|
||||
Key("s", "stage", "stage", ("stage",)),
|
||||
Key("u", "unstage", "unstage", ("unstage",)),
|
||||
Key("d", "discard", "discard", ("discard",)),
|
||||
Key("C", "commit the staged files", "commit", ("commit",)),
|
||||
Key("m", "amend the last commit", "amend", ("amend",)),
|
||||
]),
|
||||
("View", True, [
|
||||
Key("r", "refresh", "refresh", ("refresh",)),
|
||||
Key("?", "this list", "keys", ("help",)),
|
||||
Key("esc", "close the view", "", ("close",)),
|
||||
]),
|
||||
(
|
||||
"Navigate",
|
||||
True,
|
||||
[
|
||||
Key("] [", "next / previous change (wraps)", "change", ("next_change", "prev_change")),
|
||||
Key("n p", "next / previous file (wraps)", "file", ("next_file", "prev_file")),
|
||||
Key("o \u23ce", "open the real file at this line", "open", ("open",)),
|
||||
Key("j k", "down / up one line (vim)", "", ("line_down", "line_up")),
|
||||
],
|
||||
),
|
||||
(
|
||||
"Panels",
|
||||
True,
|
||||
[
|
||||
Key("f", "changed files", "files", ("files",)),
|
||||
Key("c", "recent commits", "commits", ("commits",)),
|
||||
],
|
||||
),
|
||||
(
|
||||
"Actions",
|
||||
False,
|
||||
[
|
||||
Key("s", "stage", "stage", ("stage",)),
|
||||
Key("u", "unstage", "unstage", ("unstage",)),
|
||||
Key("d", "discard", "discard", ("discard",)),
|
||||
Key("C", "commit the staged files", "commit", ("commit",)),
|
||||
Key("m", "amend the last commit", "amend", ("amend",)),
|
||||
],
|
||||
),
|
||||
(
|
||||
"View",
|
||||
True,
|
||||
[
|
||||
Key("r", "refresh", "refresh", ("refresh",)),
|
||||
Key("?", "this list", "keys", ("help",)),
|
||||
Key("esc", "close the view", "", ("close",)),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
||||
KEYS = [key for _, _, group in KEY_GROUPS for key in group]
|
||||
|
||||
KEY_HINTS = " ".join("{} {}".format(k.keys, k.short) for k in KEYS if k.short)
|
||||
KEY_HINTS = " ".join(f"{k.keys} {k.short}" for k in KEYS if k.short)
|
||||
|
||||
# the popup font is the editor's, so the key column is padded to a fixed width in characters
|
||||
_KEY_WIDTH = max(len(k.keys) for k in KEYS)
|
||||
@@ -242,7 +258,7 @@ def render(view, st):
|
||||
view.add_regions(KEY_INS_CHAR, ins_chars, SCOPE_INS_CHAR, flags=sublime.DRAW_NO_OUTLINE)
|
||||
|
||||
ins, dele = parse.counts(lines)
|
||||
_finish(view, st, ins, dele, "⟐ {}".format(os.path.basename(st.change.path)))
|
||||
_finish(view, st, ins, dele, f"⟐ {os.path.basename(st.change.path)}")
|
||||
view.sel().clear()
|
||||
view.sel().add(sublime.Region(index_point(view, 0)))
|
||||
view.set_viewport_position((0, 0), False)
|
||||
@@ -311,6 +327,11 @@ def _char_regions(lines, blocks, starts):
|
||||
return deleted, inserted
|
||||
|
||||
|
||||
def _totals(files):
|
||||
"""Summed numstat counts; binary files carry None counts and add nothing"""
|
||||
return sum(c.insertions or 0 for c in files), sum(c.deletions or 0 for c in files)
|
||||
|
||||
|
||||
def _summary_html(st):
|
||||
"""Line above the header: the whole commit on one line, or how much of the tree is staged"""
|
||||
if not st.files and not st.commit:
|
||||
@@ -320,8 +341,12 @@ def _summary_html(st):
|
||||
else:
|
||||
# staged means "has something staged": a partially staged file counts as staged only
|
||||
staged = sum(1 for c in st.files if c.staged)
|
||||
text = "{} staged, {} unstaged".format(staged, len(st.files) - staged)
|
||||
return '<div class="summary">{}</div>'.format(text)
|
||||
insertions, deletions = _totals(st.files)
|
||||
text = (
|
||||
f"{staged} staged, {len(st.files) - staged} unstaged"
|
||||
f' · <span class="del">-{deletions}</span> <span class="ins">+{insertions}</span>'
|
||||
)
|
||||
return f'<div class="summary">{text}</div>'
|
||||
|
||||
|
||||
def _commit_parts(st):
|
||||
@@ -329,22 +354,17 @@ def _commit_parts(st):
|
||||
info = st.commit
|
||||
parts = []
|
||||
if info:
|
||||
parts.append('<span class="hash">{}</span>'.format(html.escape(info.short)))
|
||||
parts.append(f'<span class="hash">{html.escape(info.short)}</span>')
|
||||
parts.append(html.escape(info.author))
|
||||
parts.append('<span class="when">{}</span>'.format(html.escape(info.date)))
|
||||
# binary files carry None counts but still changed, so they count toward the file total
|
||||
insertions = sum(c.insertions or 0 for c in st.files)
|
||||
deletions = sum(c.deletions or 0 for c in st.files)
|
||||
parts.append(
|
||||
'{} changed <span class="del">-{}</span> <span class="ins">+{}</span>'.format(
|
||||
file_count(len(st.files)), deletions, insertions
|
||||
)
|
||||
)
|
||||
parts.append(f'<span class="when">{html.escape(info.date)}</span>')
|
||||
# binary files add nothing to the line totals but still count toward the file total
|
||||
insertions, deletions = _totals(st.files)
|
||||
parts.append(f"{file_count(len(st.files))} changed" f' <span class="del">-{deletions}</span> <span class="ins">+{insertions}</span>')
|
||||
if info:
|
||||
message = html.escape(info.subject)
|
||||
body = info.body.strip().splitlines()
|
||||
if body:
|
||||
message += ' <span class="body">— {}</span>'.format(html.escape(body[0]))
|
||||
message += f' <span class="body">— {html.escape(body[0])}</span>'
|
||||
parts.append(message)
|
||||
return parts
|
||||
|
||||
@@ -355,14 +375,14 @@ def header_html(st, ins, dele):
|
||||
if change is None:
|
||||
title = '<span class="path">vDiff</span>'
|
||||
else:
|
||||
title = '<span class="path">{}</span>'.format(html.escape(change.path))
|
||||
title = f'<span class="path">{html.escape(change.path)}</span>'
|
||||
if change.old_path:
|
||||
title += ' <span class="old">← {}</span>'.format(html.escape(change.old_path))
|
||||
title += ' <span class="del">-{}</span> <span class="ins">+{}</span>'.format(dele, ins)
|
||||
title += f' <span class="old">← {html.escape(change.old_path)}</span>'
|
||||
title += f' <span class="del">-{dele}</span> <span class="ins">+{ins}</span>'
|
||||
if not st.in_commit:
|
||||
state = "staged" if change.staged else STATUS_NAMES.get(change.status, "")
|
||||
if state:
|
||||
title += ' <span class="state">{}</span>'.format(state)
|
||||
title += f' <span class="state">{state}</span>'
|
||||
|
||||
actions = []
|
||||
if change is not None and not st.in_commit:
|
||||
@@ -375,8 +395,9 @@ def header_html(st, ins, dele):
|
||||
actions.append('<a href="commits">Commits</a>')
|
||||
actions.append('<a href="help" title="keys">?</a>')
|
||||
|
||||
return '<body id="vdiff-header"><style>{}</style>{}<div>{}<span class="actions">{}</span></div></body>'.format(
|
||||
HEADER_CSS, _summary_html(st), title, "".join(actions)
|
||||
return (
|
||||
f'<body id="vdiff-header"><style>{HEADER_CSS}</style>{_summary_html(st)}'
|
||||
f'<div>{title}<span class="actions">{"".join(actions)}</span></div></body>'
|
||||
)
|
||||
|
||||
|
||||
@@ -406,17 +427,18 @@ def help_html(st):
|
||||
heading = html.escape(title)
|
||||
if dim:
|
||||
heading += ' <span class="note">uncommitted only</span>'
|
||||
parts.append('<div class="group">{}</div>'.format(heading))
|
||||
parts.append(f'<div class="group">{heading}</div>')
|
||||
# one class per element: a compound selector would silently drop the rest of HELP_CSS
|
||||
row_class, key_class = ("dim", "kdim") if dim else ("row", "k")
|
||||
for key in group:
|
||||
row = '<span class="{}">{}</span>{}{}'.format(
|
||||
key_class, html.escape(key.keys), " " * (_KEY_WIDTH - len(key.keys) + 2), html.escape(key.label)
|
||||
row = (
|
||||
f'<span class="{key_class}">{html.escape(key.keys)}</span>'
|
||||
f'{" " * (_KEY_WIDTH - len(key.keys) + 2)}{html.escape(key.label)}'
|
||||
)
|
||||
if len(key.actions) == 1 and not dim:
|
||||
row = '<a href="{}">{}</a>'.format(key.actions[0], row)
|
||||
parts.append('<div class="{}">{}</div>'.format(row_class, row))
|
||||
return '<body id="vdiff-help"><style>{}</style>{}</body>'.format(HELP_CSS, "".join(parts))
|
||||
row = f'<a href="{key.actions[0]}">{row}</a>'
|
||||
parts.append(f'<div class="{row_class}">{row}</div>')
|
||||
return f'<body id="vdiff-help"><style>{HELP_CSS}</style>{"".join(parts)}</body>'
|
||||
|
||||
|
||||
def show_help(view, st):
|
||||
|
||||
@@ -29,12 +29,12 @@ def apply_git_binary():
|
||||
|
||||
def file_count(count):
|
||||
"""'1 file' / '3 files' for a message"""
|
||||
return "{} {}".format(count, "file" if count == 1 else "files")
|
||||
return f'{count} {"file" if count == 1 else "files"}'
|
||||
|
||||
|
||||
def status(message):
|
||||
"""Status-bar message with the plugin prefix"""
|
||||
sublime.status_message("vDiff: {}".format(message))
|
||||
sublime.status_message(f"vDiff: {message}")
|
||||
|
||||
|
||||
def run_async(work, done):
|
||||
|
||||
Reference in New Issue
Block a user