From 276f1ed139c9194ec2c415acd3919cac9b251872 Mon Sep 17 00:00:00 2001 From: Ben Felder Date: Tue, 25 Feb 2020 14:07:36 +0100 Subject: [PATCH 1/7] Duplicate CheatSheet command --- Default.sublime-commands | 7 +- Main.sublime-menu | 5 ++ sublime_keymaps.py | 143 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+), 1 deletion(-) diff --git a/Default.sublime-commands b/Default.sublime-commands index 6d4aacc..3ea2d40 100644 --- a/Default.sublime-commands +++ b/Default.sublime-commands @@ -4,9 +4,14 @@ "caption": "Keymaps: Cheat Sheet", "command": "cheat_sheet" }, + { + "id": "markdown_cheat_sheet", + "caption": "Keymaps: Markdown Cheat Sheet", + "command": "markdown_cheat_sheet" + }, { "id": "find_keymap", "caption": "Keymaps: Find a keymap for...", "command": "find_keymap" } -] \ No newline at end of file +] diff --git a/Main.sublime-menu b/Main.sublime-menu index 640c5e3..2a22280 100644 --- a/Main.sublime-menu +++ b/Main.sublime-menu @@ -17,6 +17,11 @@ "id": "cheat_sheet", "caption": "Cheat Sheet", "command": "cheat_sheet" + }, + { + "id": "markdown_cheat_sheet", + "caption": "Markdown Cheat Sheet", + "command": "markdown_cheat_sheet" } ] } diff --git a/sublime_keymaps.py b/sublime_keymaps.py index fed3a38..60c736a 100644 --- a/sublime_keymaps.py +++ b/sublime_keymaps.py @@ -247,6 +247,14 @@ def run(self, edit): do(renderer, keymap_counter) +class MarkdownCheatSheetCommand(sublime_plugin.TextCommand): + def run(self, edit): + settings = Settings(self.view.settings().get("keymaps", {})) + keymap_counter = KeymapScanCounter() + renderer = MarkdownCheatSheetRenderer(settings, self.view.window(), keymap_counter) + do(renderer, keymap_counter) + + class FindKeymapCommand(sublime_plugin.TextCommand): def run(self, edit): settings = Settings(self.view.settings().get("keymaps", {})) @@ -445,6 +453,141 @@ def extract(self): } +class MarkdownCheatSheetRenderer: + def __init__(self, settings, window, keymap_counter): + self.settings = settings + self.window = window + self.keymap_counter = keymap_counter + + @property + def view_name(self): + """The name of the new keymaps view. Defined in settings.""" + return self.settings["keymaps_title"] + + @property + def header(self): + hr = "+ {} +".format("-" * (LINE_SIZE - 4)) + hr_ = ( + "{hr}\n| " + + MY_NAME + + " v" + + VERSION + + " @ {0:<" + + str(LINE_SIZE - 9 - MY_NAME.__len__() - VERSION.__len__()) + + "} |\n| {1:<76} |\n{hr}\n" + ) + + if self.settings["show_pretty_keys"]: + if sublime.platform() != "osx": + hr_ = ( + hr_ + + "\n" + + "{} - CTRL, {} - ALT, {} - SHIFT".format( + PRETTY_KEYS["CTRL"], PRETTY_KEYS["ALT"], PRETTY_KEYS["SHIFT"] + ).center(LINE_SIZE) + + "\n" + ) + + return hr_.format( + datetime.now() + .strftime("%A %d %B %Y %H:%M") + .encode("utf-8") + .decode("utf-8"), + "{} keymaps found".format(self.keymap_counter), + hr=hr, + ) + + @property + def view(self): + existing_keymaps = [ + v + for v in self.window.views() + if v.name() == self.view_name and v.is_scratch() + ] + if existing_keymaps: + v = existing_keymaps[0] + else: + v = self.window.new_file() + v.set_name(self.view_name) + v.set_scratch(True) + v.settings().set("cheat_sheet", True) + return v + + def format(self, packages): + key_func = lambda m: m["package"] + packages = sorted(packages, key=key_func) + + for package, keymaps in groupby(packages, key=key_func): + keymaps = list(keymaps) + if keymaps: + yield ("header", "{} ({})".format(package, len(keymaps)), {}) + + for idx, m in enumerate(keymaps, 1): + keys = "" + for key_token in m["keys"]: + keys = keys + "[ " + " ".join(key_token) + " ]" + if self.settings["show_pretty_keys"]: + d = PRETTY_KEYS + pattern = re.compile( + r"\b(" + + "|".join(re.escape(key) for key in d.keys()) + + r")\b" + ) + keys = pattern.sub(lambda x: d[x.group()], keys) + line = "{}: {}".format(keys.rjust(LINE_SIZE // 2), m["caption"]) + yield ("keymap", line, m) + + def render(self, formatted_keymaps): + """This blocks the main thread, so make it quick""" + # Header + keymaps_view = self.view + keymaps_view.run_command("select_all") + keymaps_view.run_command("right_delete") + keymaps_view.run_command("append", {"characters": self.header}) + + # Region : match_dicts + regions = {} + + # Keymap sections + for linetype, line, data in formatted_keymaps: + insert_point = keymaps_view.size() + if linetype == "keymap": + insert_space = insert_point + line_ = line.lstrip() + keymaps_view.run_command( + "append", + {"characters": "{}".format(" " * (len(line) - len(line_)))}, + ) + insert_point = insert_space + (keymaps_view.size() - insert_space) + keymaps_view.run_command("append", {"characters": line_}) + rgn = sublime.Region(insert_point, keymaps_view.size()) + regions[(rgn.a, rgn.b)] = (rgn, data) + else: # 'header' + keymaps_view.run_command( + "append", + {"characters": "\n\n" + line.center(LINE_SIZE) + "\n"}, + ) + keymaps_view.run_command("append", {"characters": "\n"}) + keymaps_view.add_regions("keymaps", [v[0] for k, v in regions.items()], "") + + # Store {Region : data} map in settings + # TODO: Abstract this out to a storage class Storage.get(region) ==> data dict + # Region() cannot be stored in settings, so convert to a primitive type + # d_ = regions + d_ = {"{},{}".format(k[0], k[1]): v[1] for k, v in regions.items()} + keymaps_view.settings().set("keymap_regions", d_) + + # Set syntax and settings + keymaps_view.set_syntax_file( + "Packages/" + MY_NAME + "/cheat_sheet.hidden-tmLanguage" + ) + keymaps_view.settings().set("line_padding_bottom", 2) + keymaps_view.settings().set("line_padding_top", 2) + keymaps_view.settings().set("word_wrap", False) + keymaps_view.settings().set("command_mode", True) + self.window.focus_view(keymaps_view) + + class CheatSheetRenderer: def __init__(self, settings, window, keymap_counter): self.settings = settings From 1599a87ab37680e13a28e66c786a600a725cef0a Mon Sep 17 00:00:00 2001 From: Ben Felder Date: Tue, 25 Feb 2020 14:59:00 +0100 Subject: [PATCH 2/7] Implement rendering of lines for plain keys --- sublime_keymaps.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/sublime_keymaps.py b/sublime_keymaps.py index 60c736a..0cd559c 100644 --- a/sublime_keymaps.py +++ b/sublime_keymaps.py @@ -477,16 +477,15 @@ def header(self): + "} |\n| {1:<76} |\n{hr}\n" ) - if self.settings["show_pretty_keys"]: - if sublime.platform() != "osx": - hr_ = ( - hr_ - + "\n" - + "{} - CTRL, {} - ALT, {} - SHIFT".format( - PRETTY_KEYS["CTRL"], PRETTY_KEYS["ALT"], PRETTY_KEYS["SHIFT"] - ).center(LINE_SIZE) - + "\n" - ) + if self.settings["show_pretty_keys"] and sublime.platform() != "osx": + hr_ = ( + hr_ + + "\n" + + "{} - CTRL, {} - ALT, {} - SHIFT".format( + PRETTY_KEYS["CTRL"], PRETTY_KEYS["ALT"], PRETTY_KEYS["SHIFT"] + ).center(LINE_SIZE) + + "\n" + ) return hr_.format( datetime.now() @@ -525,7 +524,7 @@ def format(self, packages): for idx, m in enumerate(keymaps, 1): keys = "" for key_token in m["keys"]: - keys = keys + "[ " + " ".join(key_token) + " ]" + keys = keys + " " + " ".join(key_token) if self.settings["show_pretty_keys"]: d = PRETTY_KEYS pattern = re.compile( @@ -534,7 +533,9 @@ def format(self, packages): + r")\b" ) keys = pattern.sub(lambda x: d[x.group()], keys) - line = "{}: {}".format(keys.rjust(LINE_SIZE // 2), m["caption"]) + justif_keys = keys.rjust(LINE_SIZE // 2) + justif_capts = m["caption"].ljust(LINE_SIZE // 2) + line = "| {} | {} |".format(justif_keys, justif_capts) yield ("keymap", line, m) def render(self, formatted_keymaps): From ee57f8c8f9eae836a6072e57fa663831c2a8bd8e Mon Sep 17 00:00:00 2001 From: Ben Felder Date: Tue, 25 Feb 2020 15:50:36 +0100 Subject: [PATCH 3/7] Implement header generation --- sublime_keymaps.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sublime_keymaps.py b/sublime_keymaps.py index 0cd559c..516683f 100644 --- a/sublime_keymaps.py +++ b/sublime_keymaps.py @@ -564,10 +564,8 @@ def render(self, formatted_keymaps): rgn = sublime.Region(insert_point, keymaps_view.size()) regions[(rgn.a, rgn.b)] = (rgn, data) else: # 'header' - keymaps_view.run_command( - "append", - {"characters": "\n\n" + line.center(LINE_SIZE) + "\n"}, - ) + hdr_str = "\n\n##{:>45}\n|||\n|-|-|".format(line) + keymaps_view.run_command("append", {"characters": hdr_str}) keymaps_view.run_command("append", {"characters": "\n"}) keymaps_view.add_regions("keymaps", [v[0] for k, v in regions.items()], "") From b9fb0e1ef605201230a6521b96a89d585216e8d9 Mon Sep 17 00:00:00 2001 From: Ben Felder Date: Tue, 25 Feb 2020 15:57:04 +0100 Subject: [PATCH 4/7] Let syntax be determined automatically --- sublime_keymaps.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/sublime_keymaps.py b/sublime_keymaps.py index 516683f..59ddfba 100644 --- a/sublime_keymaps.py +++ b/sublime_keymaps.py @@ -577,9 +577,6 @@ def render(self, formatted_keymaps): keymaps_view.settings().set("keymap_regions", d_) # Set syntax and settings - keymaps_view.set_syntax_file( - "Packages/" + MY_NAME + "/cheat_sheet.hidden-tmLanguage" - ) keymaps_view.settings().set("line_padding_bottom", 2) keymaps_view.settings().set("line_padding_top", 2) keymaps_view.settings().set("word_wrap", False) From 8f205a23ac28d77c737baa03ada7726c724ff888 Mon Sep 17 00:00:00 2001 From: Ben Felder Date: Tue, 25 Feb 2020 16:09:01 +0100 Subject: [PATCH 5/7] Implement top level section --- sublime_keymaps.py | 38 +++++++++----------------------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/sublime_keymaps.py b/sublime_keymaps.py index 59ddfba..cbff778 100644 --- a/sublime_keymaps.py +++ b/sublime_keymaps.py @@ -466,35 +466,15 @@ def view_name(self): @property def header(self): - hr = "+ {} +".format("-" * (LINE_SIZE - 4)) - hr_ = ( - "{hr}\n| " - + MY_NAME - + " v" - + VERSION - + " @ {0:<" - + str(LINE_SIZE - 9 - MY_NAME.__len__() - VERSION.__len__()) - + "} |\n| {1:<76} |\n{hr}\n" - ) - - if self.settings["show_pretty_keys"] and sublime.platform() != "osx": - hr_ = ( - hr_ - + "\n" - + "{} - CTRL, {} - ALT, {} - SHIFT".format( - PRETTY_KEYS["CTRL"], PRETTY_KEYS["ALT"], PRETTY_KEYS["SHIFT"] - ).center(LINE_SIZE) - + "\n" - ) - - return hr_.format( - datetime.now() - .strftime("%A %d %B %Y %H:%M") - .encode("utf-8") - .decode("utf-8"), - "{} keymaps found".format(self.keymap_counter), - hr=hr, - ) + hr = "# Sublime Keymaps CheatSheet\n- {}\n- {}\n- {}\n" + version = "{} @ {}".format(MY_NAME, VERSION) + timestamp = datetime.now() \ + .strftime("%A %d %B %Y %H:%M") \ + .encode("utf-8") \ + .decode("utf-8") + num_keymaps = "{} keymaps found".format(self.keymap_counter) + hr = hr.format(version, timestamp, num_keymaps) + return hr @property def view(self): From 5244bf5fbfef22236a00846fa8b1a28e0b8b777b Mon Sep 17 00:00:00 2001 From: Ben Felder Date: Tue, 25 Feb 2020 16:10:02 +0100 Subject: [PATCH 6/7] Suppress flake8 line length complaint --- sublime_keymaps.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sublime_keymaps.py b/sublime_keymaps.py index cbff778..3632981 100644 --- a/sublime_keymaps.py +++ b/sublime_keymaps.py @@ -251,7 +251,7 @@ class MarkdownCheatSheetCommand(sublime_plugin.TextCommand): def run(self, edit): settings = Settings(self.view.settings().get("keymaps", {})) keymap_counter = KeymapScanCounter() - renderer = MarkdownCheatSheetRenderer(settings, self.view.window(), keymap_counter) + renderer = MarkdownCheatSheetRenderer(settings, self.view.window(), keymap_counter) # noqa: flake8 E501 do(renderer, keymap_counter) From 24ae0dcca91c0899a4ddbe4f4ce71003e58f6387 Mon Sep 17 00:00:00 2001 From: Ben Felder Date: Tue, 25 Feb 2020 16:13:01 +0100 Subject: [PATCH 7/7] Update message and Changelog --- CHANGELOG.md | 1 + messages/1.4.0.txt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ece296a..7300328 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### v1.4.0 * Dropped support for Sublime Text 2 +* Export to MarkDown via the new command: "Keymaps: Markdown Cheat Sheet" ### v1.3.2 diff --git a/messages/1.4.0.txt b/messages/1.4.0.txt index 9319d2c..91df865 100644 --- a/messages/1.4.0.txt +++ b/messages/1.4.0.txt @@ -4,7 +4,7 @@ Install a version below v1.4.0 to continue using on Sublime Text 2. New features in Keymaps v1.4.0: - +- Export to MarkDown via the new command: "Keymaps: Markdown Cheat Sheet"