891 lines
28 KiB
Python
891 lines
28 KiB
Python
import itertools
|
|
import math
|
|
import re
|
|
from collections import defaultdict
|
|
from itertools import islice
|
|
from textwrap import wrap
|
|
from typing import Any, Iterable, Tuple
|
|
|
|
from talon import Context, Module, actions, imgui, registry, settings
|
|
|
|
mod = Module()
|
|
mod.list("help_contexts", desc="list of available contexts")
|
|
mod.tag("help_open", "tag for commands that are available only when help is visible")
|
|
mod.setting(
|
|
"help_max_contexts_per_page",
|
|
type=int,
|
|
default=20,
|
|
desc="Max contexts to display per page in help",
|
|
)
|
|
mod.setting(
|
|
"help_max_command_lines_per_page",
|
|
type=int,
|
|
default=50,
|
|
desc="Max lines of command to display per page in help",
|
|
)
|
|
mod.setting(
|
|
"help_sort_contexts_by_specificity",
|
|
type=bool,
|
|
default=True,
|
|
desc="If true contexts are sorted by specificity before alphabetically. If false, contexts are just sorted alphabetically.",
|
|
)
|
|
|
|
ctx = Context()
|
|
# context name -> commands
|
|
context_command_map = {}
|
|
|
|
# rule word -> Set[(context name, rule)]
|
|
rule_word_map: dict[str, set[tuple[str, str]]] = defaultdict(set)
|
|
search_phrase = None
|
|
|
|
# context name -> actual context
|
|
context_map = {}
|
|
|
|
current_context_page = 1
|
|
# sorted list of diplay names
|
|
sorted_display_list = []
|
|
# display names -> context name
|
|
display_name_to_context_name_map = {}
|
|
selected_context = None
|
|
selected_context_page = 1
|
|
|
|
total_page_count = 1
|
|
|
|
cached_active_contexts_list = []
|
|
|
|
live_update = True
|
|
show_enabled_contexts_only = False
|
|
|
|
selected_list = None
|
|
current_list_page = 1
|
|
|
|
|
|
def update_title():
|
|
global live_update
|
|
global show_enabled_contexts_only
|
|
|
|
if live_update:
|
|
if gui_context_help.showing:
|
|
if selected_context is None:
|
|
refresh_context_command_map(show_enabled_contexts_only)
|
|
else:
|
|
update_active_contexts_cache(registry.last_active_contexts)
|
|
if gui_operators.showing:
|
|
update_operators_text()
|
|
|
|
|
|
@imgui.open(y=0)
|
|
def gui_formatters(gui: imgui.GUI):
|
|
global formatters_words
|
|
if formatters_reformat:
|
|
gui.text("re-formatters help")
|
|
else:
|
|
gui.text("formatters help")
|
|
gui.line()
|
|
|
|
for key, val in formatters_words.items():
|
|
gui.text(f"{val}: {key}")
|
|
|
|
gui.spacer()
|
|
gui.text("* prose formatter")
|
|
gui.spacer()
|
|
if gui.button("Help close"):
|
|
gui_formatters.hide()
|
|
|
|
|
|
def update_operators_text():
|
|
"""For operators implemented for the active language, map spoken forms including operator prefix to
|
|
the operator text for operators implemented as text insertion
|
|
or an asterisk for operators implemented as a function call.
|
|
"""
|
|
global operators_text, total_page_count
|
|
try:
|
|
operators = actions.user.code_get_operators()
|
|
|
|
# Associate the names of the operator lists with the corresponding prefix
|
|
op_list_names = ["array", "assignment", "bitwise", "lambda", "math", "pointer"]
|
|
names_with_prefix = [(name, "op") for name in op_list_names]
|
|
names_with_prefix.append(("math_comparison", "is"))
|
|
|
|
# Fill in the list by iterating over the operator lists
|
|
operators_text = []
|
|
has_operator_without_text_implementation = False
|
|
for name, prefix in names_with_prefix:
|
|
operators_list = actions.user.talon_get_active_registry_list(
|
|
"user.code_operators_" + name
|
|
)
|
|
has_added_first_list_item = False
|
|
for operator_name, operator_text in sorted(operators_list.items()):
|
|
# Only display operators implemented for the active language
|
|
if operator_text in operators:
|
|
# If the operator is implemented as text insertion,
|
|
# display the operator text
|
|
operator = operators.get(operator_text)
|
|
if type(operator) == str:
|
|
text = ": " + operator
|
|
# Otherwise display the operator name from list
|
|
else:
|
|
has_operator_without_text_implementation = True
|
|
text = "*"
|
|
# Only add the header if an item in the list is defined in operators
|
|
if not has_added_first_list_item:
|
|
has_added_first_list_item = True
|
|
operators_text.append(f"{name} operators:")
|
|
|
|
operators_text.append(f" {prefix} {operator_name}{text}")
|
|
if has_operator_without_text_implementation:
|
|
operators_text.append(
|
|
"* operator is implemented as a function call and cannot be displayed"
|
|
)
|
|
page_size = settings.get("user.help_max_command_lines_per_page")
|
|
total_page_count = math.ceil(len(operators_text) / page_size)
|
|
# This exception will get raised if there is no operators object defined in the active context
|
|
except NotImplementedError:
|
|
operators_text = None
|
|
|
|
|
|
@imgui.open(y=0)
|
|
def gui_operators(gui: imgui.GUI):
|
|
global operators_text
|
|
|
|
if operators_text is None:
|
|
gui.text("Help: Operators (1/1)")
|
|
gui.line()
|
|
gui.text("There is no active programming language when you opened this menu")
|
|
gui.text("or the language does not have operator support.")
|
|
else:
|
|
page_size = settings.get("user.help_max_command_lines_per_page")
|
|
page_start = page_size * (current_list_page - 1)
|
|
page_end = page_start + page_size
|
|
gui.text(f"Help: Operators ({current_list_page}/{total_page_count})")
|
|
gui.line()
|
|
for text in operators_text[page_start:page_end]:
|
|
gui.text(text)
|
|
|
|
if total_page_count > 1:
|
|
gui.spacer()
|
|
if gui.button("Help next"):
|
|
actions.user.help_next()
|
|
|
|
if gui.button("Help previous"):
|
|
actions.user.help_previous()
|
|
gui.spacer()
|
|
if gui.button("Help close"):
|
|
gui_operators.hide()
|
|
|
|
|
|
def format_context_title(context_name: str) -> str:
|
|
global cached_active_contexts_list
|
|
return "{} [{}]".format(
|
|
context_name,
|
|
(
|
|
"ACTIVE"
|
|
if context_map.get(context_name, None) in cached_active_contexts_list
|
|
else "INACTIVE"
|
|
),
|
|
)
|
|
|
|
|
|
def format_context_button(index: int, context_label: str, context_name: str) -> str:
|
|
global cached_active_contexts_list
|
|
global show_enabled_contexts_only
|
|
|
|
if not show_enabled_contexts_only:
|
|
return "{}. {}{}".format(
|
|
index,
|
|
context_label,
|
|
(
|
|
"*"
|
|
if context_map.get(context_name, None) in cached_active_contexts_list
|
|
else ""
|
|
),
|
|
)
|
|
else:
|
|
return f"{index}. {context_label} "
|
|
|
|
|
|
# translates 1-based index -> actual index in sorted_context_map_keys
|
|
def get_context_page(index: int) -> int:
|
|
return math.ceil(index / settings.get("user.help_max_contexts_per_page"))
|
|
|
|
|
|
def get_total_context_pages() -> int:
|
|
return math.ceil(
|
|
len(sorted_display_list) / settings.get("user.help_max_contexts_per_page")
|
|
)
|
|
|
|
|
|
def get_current_context_page_length() -> int:
|
|
start_index = (current_context_page - 1) * settings.get(
|
|
"user.help_max_contexts_per_page"
|
|
)
|
|
return len(
|
|
sorted_display_list[
|
|
start_index : start_index + settings.get("user.help_max_contexts_per_page")
|
|
]
|
|
)
|
|
|
|
|
|
def get_command_line_count(command: tuple[str, str]) -> int:
|
|
"""This should be kept in sync with draw_commands"""
|
|
_, body = command
|
|
lines = len(body.split("\n"))
|
|
if lines == 1:
|
|
return 1
|
|
else:
|
|
return lines + 1
|
|
|
|
|
|
def get_pages(item_line_counts: list[int]) -> list[int]:
|
|
"""Given some set of indivisible items with given line counts,
|
|
return the page number each item should appear on.
|
|
|
|
If an item will cross a page boundary, it is moved to the next page,
|
|
so that pages may be shorter than the maximum lenth, but not longer. The only
|
|
exception is when an item is longer than the maximum page length, in which
|
|
case that item will be placed on a longer page.
|
|
"""
|
|
current_page_line_count = 0
|
|
current_page = 1
|
|
pages = []
|
|
for line_count in item_line_counts:
|
|
if line_count + current_page_line_count > settings.get(
|
|
"user.help_max_command_lines_per_page"
|
|
):
|
|
if current_page_line_count == 0:
|
|
# Special case, render a larger page.
|
|
page = current_page
|
|
current_page_line_count = 0
|
|
else:
|
|
page = current_page + 1
|
|
current_page_line_count = line_count
|
|
current_page += 1
|
|
else:
|
|
current_page_line_count += line_count
|
|
page = current_page
|
|
pages.append(page)
|
|
return pages
|
|
|
|
|
|
@imgui.open(y=0)
|
|
def gui_context_help(gui: imgui.GUI):
|
|
global context_command_map
|
|
global current_context_page
|
|
global selected_context
|
|
global selected_context_page
|
|
global sorted_display_list
|
|
global show_enabled_contexts_only
|
|
global cached_active_contexts_list
|
|
global total_page_count
|
|
global search_phrase
|
|
|
|
# if no selected context, draw the contexts
|
|
if selected_context is None and search_phrase is None:
|
|
total_page_count = get_total_context_pages()
|
|
|
|
if not show_enabled_contexts_only:
|
|
gui.text(
|
|
f"Help: All ({current_context_page}/{total_page_count}) (* = active)"
|
|
)
|
|
else:
|
|
gui.text(
|
|
"Help: Active Contexts Only ({}/{})".format(
|
|
current_context_page, total_page_count
|
|
)
|
|
)
|
|
|
|
gui.line()
|
|
|
|
current_item_index = 1
|
|
current_selection_index = 1
|
|
current_group = ""
|
|
for display_name, group, _ in sorted_display_list:
|
|
target_page = get_context_page(current_item_index)
|
|
context_name = display_name_to_context_name_map[display_name]
|
|
if current_context_page == target_page:
|
|
if current_group != group:
|
|
if current_group:
|
|
gui.line()
|
|
gui.text(f"{group}:")
|
|
current_group = group
|
|
|
|
button_name = format_context_button(
|
|
current_selection_index,
|
|
display_name,
|
|
context_name,
|
|
)
|
|
|
|
if gui.button(button_name):
|
|
selected_context = context_name
|
|
current_selection_index = current_selection_index + 1
|
|
|
|
current_item_index += 1
|
|
|
|
if total_page_count > 1:
|
|
gui.spacer()
|
|
if gui.button("Help next"):
|
|
actions.user.help_next()
|
|
|
|
if gui.button("Help previous"):
|
|
actions.user.help_previous()
|
|
|
|
# if there's a selected context, draw the commands for it
|
|
else:
|
|
if selected_context is not None:
|
|
draw_context_commands(gui)
|
|
elif search_phrase is not None:
|
|
draw_search_commands(gui)
|
|
|
|
gui.spacer()
|
|
if total_page_count > 1:
|
|
if gui.button("Help next"):
|
|
actions.user.help_next()
|
|
|
|
if gui.button("Help previous"):
|
|
actions.user.help_previous()
|
|
|
|
if gui.button("Help return"):
|
|
actions.user.help_return()
|
|
|
|
if gui.button("Help refresh"):
|
|
actions.user.help_refresh()
|
|
|
|
if gui.button("Help close"):
|
|
actions.user.help_hide()
|
|
|
|
|
|
def draw_context_commands(gui: imgui.GUI):
|
|
global selected_context
|
|
global total_page_count
|
|
global selected_context_page
|
|
|
|
context_title = format_context_title(selected_context)
|
|
title = f"Context: {context_title}"
|
|
commands = context_command_map[selected_context].items()
|
|
item_line_counts = [get_command_line_count(command) for command in commands]
|
|
pages = get_pages(item_line_counts)
|
|
total_page_count = max(pages, default=1)
|
|
draw_commands_title(gui, title)
|
|
|
|
filtered_commands = [
|
|
command
|
|
for command, page in zip(commands, pages)
|
|
if page == selected_context_page
|
|
]
|
|
|
|
draw_commands(gui, filtered_commands)
|
|
|
|
|
|
def draw_search_commands(gui: imgui.GUI):
|
|
global search_phrase
|
|
global total_page_count
|
|
global cached_active_contexts_list
|
|
global selected_context_page
|
|
|
|
title = f"Search: {search_phrase}"
|
|
commands_grouped = get_search_commands(search_phrase)
|
|
commands_flat = list(itertools.chain.from_iterable(commands_grouped.values()))
|
|
|
|
sorted_commands_grouped = sorted(
|
|
commands_grouped.items(),
|
|
key=lambda item: context_map[item[0]] not in cached_active_contexts_list,
|
|
)
|
|
|
|
pages = get_pages(
|
|
[
|
|
sum(get_command_line_count(command) for command in commands) + 3
|
|
for _, commands in sorted_commands_grouped
|
|
]
|
|
)
|
|
total_page_count = max(pages, default=1)
|
|
|
|
draw_commands_title(gui, title)
|
|
|
|
current_item_index = 1
|
|
for (context, commands), page in zip(sorted_commands_grouped, pages):
|
|
if page == selected_context_page:
|
|
gui.text(format_context_title(context))
|
|
gui.line()
|
|
draw_commands(gui, commands)
|
|
gui.spacer()
|
|
|
|
|
|
def get_search_commands(phrase: str) -> dict[str, tuple[str, str]]:
|
|
global rule_word_map
|
|
tokens = search_phrase.split(" ")
|
|
|
|
viable_commands = rule_word_map[tokens[0]]
|
|
for token in tokens[1:]:
|
|
viable_commands &= rule_word_map[token]
|
|
|
|
# sets have no stable sort order, unlike dicts
|
|
viable_commands = list(viable_commands)
|
|
viable_commands.sort()
|
|
|
|
commands_grouped = defaultdict(list)
|
|
for context, rule in viable_commands:
|
|
command = context_command_map[context][rule]
|
|
commands_grouped[context].append((rule, command))
|
|
|
|
return commands_grouped
|
|
|
|
|
|
def draw_commands_title(gui: imgui.GUI, title: str):
|
|
global selected_context_page
|
|
global total_page_count
|
|
|
|
gui.text(f"{title} ({selected_context_page}/{total_page_count})")
|
|
gui.line()
|
|
|
|
|
|
def draw_commands(gui: imgui.GUI, commands: Iterable[tuple[str, str]]):
|
|
for key, val in commands:
|
|
val = val.split("\n")
|
|
if len(val) > 1:
|
|
gui.text(f"{key}:")
|
|
for line in val:
|
|
gui.text(f" {line}")
|
|
else:
|
|
gui.text(f"{key}: {val[0]}")
|
|
|
|
|
|
def reset():
|
|
global current_context_page
|
|
global sorted_display_list
|
|
global selected_context
|
|
global search_phrase
|
|
global selected_context_page
|
|
global show_enabled_contexts_only
|
|
global display_name_to_context_name_map
|
|
global selected_list
|
|
global current_list_page
|
|
|
|
current_context_page = 1
|
|
sorted_display_list = []
|
|
selected_context = None
|
|
search_phrase = None
|
|
selected_context_page = 1
|
|
show_enabled_contexts_only = False
|
|
display_name_to_context_name_map = {}
|
|
selected_list = None
|
|
current_list_page = 1
|
|
|
|
|
|
def update_active_contexts_cache(active_contexts):
|
|
# print("update_active_contexts_cache")
|
|
global cached_active_contexts_list
|
|
cached_active_contexts_list = active_contexts
|
|
|
|
|
|
# example usage todo: make a list definable in .talon
|
|
# overrides = {"generic browser": "broswer"}
|
|
overrides = {}
|
|
|
|
|
|
def refresh_context_command_map(enabled_only=False):
|
|
active_contexts = registry.last_active_contexts
|
|
|
|
local_context_map = {}
|
|
local_display_name_to_context_name_map = {}
|
|
local_context_command_map = {}
|
|
cached_short_context_names = {}
|
|
|
|
for context_name, context in registry.contexts.items():
|
|
splits = context_name.split(".")
|
|
|
|
if "talon" == splits[-1]:
|
|
display_name = splits[-2].replace("_", " ")
|
|
|
|
short_names = actions.user.create_spoken_forms(
|
|
display_name,
|
|
generate_subsequences=False,
|
|
)
|
|
|
|
if short_names[0] in overrides:
|
|
short_names = [overrides[short_names[0]]]
|
|
elif len(short_names) == 2 and short_names[1] in overrides:
|
|
short_names = [overrides[short_names[1]]]
|
|
|
|
if enabled_only and context in active_contexts or not enabled_only:
|
|
local_context_command_map[context_name] = {}
|
|
for command_alias, val in context.commands.items():
|
|
if command_alias in registry.commands or not enabled_only:
|
|
local_context_command_map[context_name][
|
|
str(val.rule.rule)
|
|
] = val.target.code
|
|
if len(local_context_command_map[context_name]) == 0:
|
|
local_context_command_map.pop(context_name)
|
|
else:
|
|
for short_name in short_names:
|
|
cached_short_context_names[short_name] = context_name
|
|
|
|
# the last entry will contain no symbols
|
|
local_display_name_to_context_name_map[display_name] = context_name
|
|
local_context_map[context_name] = context
|
|
|
|
# Update all the global state after we've performed our calculations
|
|
global context_map
|
|
global context_command_map
|
|
global sorted_display_list
|
|
global show_enabled_contexts_only
|
|
global display_name_to_context_name_map
|
|
global rule_word_map
|
|
|
|
context_map = local_context_map
|
|
context_command_map = local_context_command_map
|
|
sorted_display_list = get_sorted_display_keys(
|
|
local_context_map,
|
|
local_display_name_to_context_name_map,
|
|
)
|
|
show_enabled_contexts_only = enabled_only
|
|
display_name_to_context_name_map = local_display_name_to_context_name_map
|
|
rule_word_map = refresh_rule_word_map(local_context_command_map)
|
|
|
|
ctx.lists["self.help_contexts"] = cached_short_context_names
|
|
update_active_contexts_cache(active_contexts)
|
|
|
|
|
|
def get_sorted_display_keys(
|
|
context_map: dict[str, Any],
|
|
display_name_to_context_name_map: dict[str, str],
|
|
):
|
|
if settings.get("user.help_sort_contexts_by_specificity"):
|
|
return get_sorted_keys_by_context_specificity(
|
|
context_map,
|
|
display_name_to_context_name_map,
|
|
)
|
|
return [
|
|
(display_name, "", 0)
|
|
for display_name in sorted(display_name_to_context_name_map.keys())
|
|
]
|
|
|
|
|
|
def get_sorted_keys_by_context_specificity(
|
|
context_map: dict[str, Any],
|
|
display_name_to_context_name_map: dict[str, str],
|
|
) -> list[Tuple[str, str, int]]:
|
|
def get_group(display_name) -> Tuple[str, str, int]:
|
|
try:
|
|
context_name = display_name_to_context_name_map[display_name]
|
|
context = context_map[context_name]
|
|
keys = context._match.keys()
|
|
if any(key for key in keys if key.startswith("app.")):
|
|
return (display_name, "Application-specific", 2)
|
|
if keys:
|
|
return (display_name, "Context-dependent", 1)
|
|
return (display_name, "Global", 0)
|
|
except Exception as ex:
|
|
return (display_name, "", 0)
|
|
|
|
grouped_list = [
|
|
get_group(display_name)
|
|
for display_name in display_name_to_context_name_map.keys()
|
|
]
|
|
return sorted(
|
|
grouped_list,
|
|
key=lambda item: (-item[2], item[0]),
|
|
)
|
|
|
|
|
|
def refresh_rule_word_map(context_command_map):
|
|
rule_word_map = defaultdict(set)
|
|
|
|
for context_name, commands in context_command_map.items():
|
|
for rule in commands:
|
|
tokens = {token for token in re.split(r"\W+", rule) if token.isalpha()}
|
|
for token in tokens:
|
|
rule_word_map[token].add((context_name, rule))
|
|
|
|
return rule_word_map
|
|
|
|
|
|
events_registered = False
|
|
|
|
|
|
def register_events(register: bool):
|
|
global events_registered
|
|
if register:
|
|
if not events_registered and live_update:
|
|
events_registered = True
|
|
# registry.register('post:update_contexts', contexts_updated)
|
|
registry.register("update_commands", commands_updated)
|
|
else:
|
|
events_registered = False
|
|
# registry.unregister('post:update_contexts', contexts_updated)
|
|
registry.unregister("update_commands", commands_updated)
|
|
|
|
|
|
def hide_all_help_guis():
|
|
gui_context_help.hide()
|
|
gui_formatters.hide()
|
|
gui_list_help.hide()
|
|
gui_operators.hide()
|
|
|
|
|
|
def paginate_list(data, SIZE=None):
|
|
chunk_size = SIZE or settings.get("user.help_max_command_lines_per_page")
|
|
it = iter(data)
|
|
for i in range(0, len(data), chunk_size):
|
|
yield {k: data[k] for k in islice(it, chunk_size)}
|
|
|
|
|
|
def draw_list_commands(gui: imgui.GUI):
|
|
global selected_list
|
|
global total_page_count
|
|
global selected_context_page
|
|
|
|
talon_list = actions.user.talon_get_active_registry_list(selected_list)
|
|
# numpages = math.ceil(len(talon_list) / SIZE)
|
|
|
|
pages_list = []
|
|
|
|
for item in paginate_list(talon_list):
|
|
pages_list.append(item)
|
|
# print(pages_list)
|
|
|
|
total_page_count = len(pages_list)
|
|
return pages_list
|
|
|
|
|
|
@imgui.open(y=0)
|
|
def gui_list_help(gui: imgui.GUI):
|
|
global total_page_count
|
|
global current_list_page
|
|
global selected_list
|
|
|
|
pages_list = draw_list_commands(gui)
|
|
total_page_count = len(pages_list)
|
|
# print(pages_list[current_page])
|
|
|
|
if total_page_count == 0:
|
|
page_info = "empty"
|
|
else:
|
|
page_info = f"{current_list_page}/{total_page_count}"
|
|
|
|
gui.text(f"List: {selected_list} ({page_info})")
|
|
|
|
# Extract description from list declaration, i.e. mod.list(..., desc=...))
|
|
if (desc := registry.decls.lists[selected_list].desc) is not None:
|
|
for line in wrap(desc):
|
|
gui.text(line)
|
|
|
|
gui.line()
|
|
|
|
if len(pages_list) > 0:
|
|
for key, value in pages_list[current_list_page - 1].items():
|
|
gui.text(f"{value}: {key}")
|
|
|
|
gui.spacer()
|
|
|
|
if total_page_count > 1:
|
|
if gui.button("Help next"):
|
|
actions.user.help_next()
|
|
|
|
if gui.button("Help previous"):
|
|
actions.user.help_previous()
|
|
|
|
if gui.button("Help return"):
|
|
actions.user.help_return()
|
|
|
|
if gui.button("Help refresh"):
|
|
actions.user.help_refresh()
|
|
|
|
if gui.button("Help close"):
|
|
actions.user.help_hide()
|
|
|
|
|
|
@mod.action_class
|
|
class Actions:
|
|
def help_list(ab: str):
|
|
"""Provides the symbol dictionary"""
|
|
# what you say is stored as a trigger
|
|
global selected_list
|
|
reset()
|
|
selected_list = ab
|
|
gui_list_help.show()
|
|
register_events(True)
|
|
ctx.tags = ["user.help_open"]
|
|
|
|
def help_formatters(ab: dict, reformat: bool):
|
|
"""Provides the list of formatter keywords"""
|
|
# what you say is stored as a trigger
|
|
global formatters_words, formatters_reformat
|
|
formatters_words = ab
|
|
formatters_reformat = reformat
|
|
reset()
|
|
hide_all_help_guis()
|
|
gui_formatters.show()
|
|
register_events(False)
|
|
ctx.tags = ["user.help_open"]
|
|
|
|
def help_operators():
|
|
"""Displays the list of operator names"""
|
|
reset()
|
|
hide_all_help_guis()
|
|
update_operators_text()
|
|
gui_operators.show()
|
|
register_events(True)
|
|
ctx.tags = ["user.help_open"]
|
|
|
|
def help_context_enabled():
|
|
"""Display contextual command info"""
|
|
reset()
|
|
refresh_context_command_map(enabled_only=True)
|
|
hide_all_help_guis()
|
|
gui_context_help.show()
|
|
register_events(True)
|
|
ctx.tags = ["user.help_open"]
|
|
|
|
def help_context():
|
|
"""Display contextual command info"""
|
|
reset()
|
|
refresh_context_command_map()
|
|
hide_all_help_guis()
|
|
gui_context_help.show()
|
|
register_events(True)
|
|
ctx.tags = ["user.help_open"]
|
|
|
|
def help_search(phrase: str):
|
|
"""Display command info for search phrase"""
|
|
global search_phrase
|
|
|
|
reset()
|
|
search_phrase = phrase
|
|
refresh_context_command_map()
|
|
hide_all_help_guis()
|
|
gui_context_help.show()
|
|
register_events(True)
|
|
ctx.tags = ["user.help_open"]
|
|
|
|
def help_selected_context(m: str):
|
|
"""Display command info for selected context"""
|
|
global selected_context
|
|
global selected_context_page
|
|
|
|
if not gui_context_help.showing:
|
|
reset()
|
|
refresh_context_command_map()
|
|
else:
|
|
selected_context_page = 1
|
|
update_active_contexts_cache(registry.last_active_contexts)
|
|
|
|
selected_context = m
|
|
hide_all_help_guis()
|
|
gui_context_help.show()
|
|
register_events(True)
|
|
ctx.tags = ["user.help_open"]
|
|
|
|
def help_next():
|
|
"""Navigates to next page"""
|
|
global current_context_page
|
|
global selected_context
|
|
global selected_context_page
|
|
global total_page_count
|
|
|
|
global current_list_page
|
|
|
|
if gui_context_help.showing:
|
|
if selected_context is None and search_phrase is None:
|
|
if current_context_page != total_page_count:
|
|
current_context_page += 1
|
|
else:
|
|
current_context_page = 1
|
|
else:
|
|
if selected_context_page != total_page_count:
|
|
selected_context_page += 1
|
|
else:
|
|
selected_context_page = 1
|
|
|
|
if gui_list_help.showing or gui_operators.showing:
|
|
if current_list_page != total_page_count:
|
|
current_list_page += 1
|
|
else:
|
|
current_list_page = 1
|
|
|
|
def help_select_index(index: int):
|
|
"""Select the context by a number"""
|
|
global sorted_display_list, selected_context
|
|
if gui_context_help.showing:
|
|
if index < settings.get("user.help_max_contexts_per_page") and (
|
|
(current_context_page - 1)
|
|
* settings.get("user.help_max_contexts_per_page")
|
|
+ index
|
|
< len(sorted_display_list)
|
|
):
|
|
if selected_context is None:
|
|
selected_context = display_name_to_context_name_map[
|
|
sorted_display_list[
|
|
(current_context_page - 1)
|
|
* settings.get("user.help_max_contexts_per_page")
|
|
+ index
|
|
][0]
|
|
]
|
|
|
|
def help_previous():
|
|
"""Navigates to previous page"""
|
|
global current_context_page
|
|
global selected_context
|
|
global selected_context_page
|
|
global total_page_count
|
|
|
|
global current_list_page
|
|
|
|
if gui_context_help.showing:
|
|
if selected_context is None and search_phrase is None:
|
|
if current_context_page != 1:
|
|
current_context_page -= 1
|
|
else:
|
|
current_context_page = total_page_count
|
|
|
|
else:
|
|
if selected_context_page != 1:
|
|
selected_context_page -= 1
|
|
else:
|
|
selected_context_page = total_page_count
|
|
|
|
if gui_list_help.showing or gui_operators.showing:
|
|
if current_list_page != total_page_count:
|
|
current_list_page -= 1
|
|
else:
|
|
current_list_page = 1
|
|
|
|
def help_return():
|
|
"""Returns to the main help window"""
|
|
global selected_context
|
|
global selected_context_page
|
|
global show_enabled_contexts_only
|
|
|
|
if gui_context_help.showing:
|
|
refresh_context_command_map(show_enabled_contexts_only)
|
|
selected_context_page = 1
|
|
selected_context = None
|
|
|
|
def help_refresh():
|
|
"""Refreshes the help"""
|
|
global show_enabled_contexts_only
|
|
global selected_context
|
|
|
|
if gui_context_help.showing:
|
|
if selected_context is None:
|
|
refresh_context_command_map(show_enabled_contexts_only)
|
|
else:
|
|
update_active_contexts_cache(registry.last_active_contexts)
|
|
|
|
def help_hide():
|
|
"""Hides the help"""
|
|
reset()
|
|
|
|
# print("help_hide - alphabet gui_alphabet: {}".format(gui_alphabet.showing))
|
|
# print(
|
|
# "help_hide - gui_context_help showing: {}".format(gui_context_help.showing)
|
|
# )
|
|
|
|
hide_all_help_guis()
|
|
refresh_context_command_map()
|
|
register_events(False)
|
|
ctx.tags = []
|
|
|
|
|
|
def commands_updated(_):
|
|
update_title()
|