├── LICENSE
├── README.md
└── all
└── hyperhelpcore
├── HyperHelp
├── bootstrap.py
├── commands.py
├── contexts.py
├── devtools.py
├── events.py
├── help
│ ├── api.txt
│ ├── authoring.txt
│ ├── bookmarks.txt
│ ├── changelog.txt
│ ├── commands.txt
│ ├── example.txt
│ ├── help_index.txt
│ ├── help_on_help.txt
│ ├── hyperhelp.json.sublime-ignored
│ ├── index.txt
│ ├── integration.txt
│ ├── key_contexts.txt
│ ├── settings.txt
│ ├── style.txt
│ └── syntax.txt
├── internalcmd.py
└── resources
│ ├── Context.sublime-menu.sublime-ignored
│ ├── Default (Linux).sublime-keymap.sublime-ignored
│ ├── Default (OSX).sublime-keymap.sublime-ignored
│ ├── Default (Windows).sublime-keymap.sublime-ignored
│ ├── HyperHelp-Help.sublime-settings.sublime-ignored
│ ├── HyperHelp.sublime-commands.sublime-ignored
│ ├── HyperHelp.sublime-settings.sublime-ignored
│ ├── Main.sublime-menu.sublime-ignored
│ ├── Preferences.sublime-settings-hints.sublime-ignored
│ ├── Symbol List - Exclusions.tmPreferences.sublime-ignored
│ ├── Symbol List - Headers.tmPreferences.sublime-ignored
│ ├── Symbol List - Title.tmPreferences.sublime-ignored
│ └── syntax
│ ├── HyperHelp-Help.sublime-syntax.sublime-ignored
│ ├── HyperHelp-Index.sublime-syntax.sublime-ignored
│ └── HyperHelpComments.tmPreferences.sublime-ignored
├── __init__.py
├── bootstrapper.py
├── common.py
├── core.py
├── data.py
├── help.py
├── help_index.py
├── index_validator.py
├── startup.py
├── validictory
├── LICENSE.txt
├── __init__.py
└── validator.py
└── view.py
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2017-2019 Terence Martin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9 | of the Software, and to permit persons to whom the Software is furnished to do
10 | so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | HyperHelp and hyperhelpcore
2 | ============================
3 |
4 | hyperhelpcore is a dependency package for Sublime Text 3 that allows package
5 | authors to provide context sensitive, hyperlinked help for their packages that
6 | is displayable directly from within Sublime Text itself.
7 |
8 | At first startup, hyperhelpcore will generate a HyperHelp package in the
9 | InstalledPackages folder to expose the help functionality, and ensure that it
10 | is always up to date.
11 |
12 | Some packages using hyperhelpcore:
13 |
14 | * [SnAPI](https://github.com/STealthy-and-haSTy/SnAPI) - View the
15 | documentation for Sublime Text directly within Sublime
16 | * [HyperHelpAuthor](https://github.com/STealthy-and-haSTy/HyperHelpAuthor) -
17 | Simple authoring tools for hyperhelpcore
18 |
19 |
20 | -------------------------------------------------------------------------------
21 |
22 |
23 | **NOTE:** This is very much still a work in progress and still being actively
24 | developed and tweaked. At this point anything and everything is subject to
25 | change without notice.
26 |
27 |
28 | -------------------------------------------------------------------------------
29 |
30 |
31 | ## License ##
32 |
33 | Copyright 2017-2019 Terence Martin
34 |
35 | Permission is hereby granted, free of charge, to any person obtaining a copy of
36 | this software and associated documentation files (the "Software"), to deal in
37 | the Software without restriction, including without limitation the rights to
38 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
39 | of the Software, and to permit persons to whom the Software is furnished to do
40 | so, subject to the following conditions:
41 |
42 | The above copyright notice and this permission notice shall be included in all
43 | copies or substantial portions of the Software.
44 |
45 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
46 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
47 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
48 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
49 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
50 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
51 | SOFTWARE.
52 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/bootstrap.py:
--------------------------------------------------------------------------------
1 | import sublime
2 |
3 | from hyperhelpcore.bootstrapper import display_topic
4 | from hyperhelpcore.common import hh_setting
5 |
6 |
7 | ### ---------------------------------------------------------------------------
8 |
9 |
10 | # When the bootstrapped system package is created or updated, the value of this
11 | # tuple is updated to the version of the dependency that is doing the
12 | # bootstrap.
13 | #
14 | # The bootstrap code looks specifically for this line, so don't modify it.
15 | __core_version_tuple = (0, 0, 0)
16 |
17 | __version_tuple = __core_version_tuple
18 | __version__ = ".".join([str(num) for num in __version_tuple])
19 |
20 |
21 | ### ---------------------------------------------------------------------------
22 |
23 |
24 | def version():
25 | """
26 | Get the currently installed version of the bootstrapped version of the
27 | package as a tuple. This is used during the bootstrap check to see if the
28 | version of the dependency has changed since the bootstrapped package was
29 | created.
30 | """
31 | return __version_tuple
32 |
33 |
34 | def plugin_loaded():
35 | """
36 | On plugin load, see if we should display an initial help topic or not.
37 | This relies on a window setting that the bootstrapper applies to whatever
38 | the current window is, and will display an appropriate topic based on what
39 | the bootstrap did.
40 | """
41 | topic = None
42 | for window in sublime.windows():
43 | settings = window.settings()
44 | if settings.has("hyperhelp.initial_topic"):
45 | topic = topic or settings.get("hyperhelp.initial_topic")
46 | settings.erase("hyperhelp.initial_topic")
47 |
48 | if topic is not None and hh_setting("show_changelog"):
49 | package, topic = topic.split(":")
50 | display_topic(package, topic)
51 |
52 |
53 | ### ---------------------------------------------------------------------------
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/contexts.py:
--------------------------------------------------------------------------------
1 | import sublime
2 | import sublime_plugin
3 |
4 | from hyperhelpcore.common import log
5 | from hyperhelpcore.common import current_help_package, current_help_file
6 | from hyperhelpcore.view import find_help_view
7 |
8 |
9 | ###----------------------------------------------------------------------------
10 |
11 |
12 | class HyperhelpContextListener(sublime_plugin.EventListener):
13 | def on_query_context(self, view, key, operator, operand, match_all):
14 | """
15 | Provide custom key binding contexts for binding keys in hyperhelp
16 | views.
17 | """
18 | if key == "hyperhelp.is_help_view":
19 | help_view = find_help_view(view.window())
20 | lhs = help_view is not None and help_view.id() == view.id()
21 | rhs = bool(operand)
22 |
23 | elif key == "hyperhelp.is_help_source":
24 | lhs = (view.match_selector(0, "text.hyperhelp.help") and
25 | view.is_read_only() == False)
26 | rhs = bool(operand)
27 |
28 | elif key == "hyperhelp.is_help":
29 | lhs = view.match_selector(0, "text.hyperhelp.help")
30 | rhs = bool(operand)
31 |
32 | elif key == "hyperhelp.is_help_index":
33 | lhs = view.match_selector(0, "text.hyperhelp.index")
34 | rhs = bool(operand)
35 |
36 | elif key == "hyperhelp.is_help_visible":
37 | lhs = find_help_view(view.window()) is not None
38 | rhs = bool(operand)
39 |
40 | elif key == "hyperhelp.is_help_package":
41 | lhs = current_help_package(window=view.window())
42 | rhs = str(operand)
43 |
44 | elif key == "hyperhelp.is_help_file":
45 | lhs = current_help_file(window=view.window())
46 | rhs = str(operand)
47 |
48 | # This one is the legacy; remove this once the others are fully
49 | # tested.
50 | elif key == "hyperhelp.is_authoring":
51 | lhs = view.is_read_only() == False
52 | rhs = bool(operand)
53 | else:
54 | return None
55 |
56 | if operator == sublime.OP_EQUAL:
57 | return lhs == rhs
58 | elif operator == sublime.OP_NOT_EQUAL:
59 | return lhs != rhs
60 |
61 | return None
62 |
63 |
64 | ###----------------------------------------------------------------------------
65 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/devtools.py:
--------------------------------------------------------------------------------
1 | import sublime
2 | import sublime_plugin
3 |
4 | import textwrap
5 |
6 | from hyperhelpcore.bootstrapper import log, BootstrapThread
7 |
8 |
9 |
10 | ###----------------------------------------------------------------------------
11 |
12 |
13 | def _wrap(msg, *args, **kwargs):
14 | return textwrap.dedent(msg.format(*args, **kwargs)).strip()
15 |
16 |
17 | def _is_developer_mode():
18 | s = sublime.load_settings("HyperHelp.sublime-settings")
19 | return s.get("developer_mode", False)
20 |
21 |
22 | ###----------------------------------------------------------------------------
23 |
24 |
25 | class HyperhelpDeveloperForceBootstrapCommand(sublime_plugin.ApplicationCommand):
26 | """
27 | Verify with the user and then, if confirmed, force hyperhelpcore to run an
28 | immediate bootstrap sequence to re-bootstrap the package.
29 |
30 | This is a developer only command; if you're not actively developing the
31 | package, you shouldn't be invoking this command without being directed to
32 | do so by the developer or other person in the know.
33 | """
34 | def run(self):
35 | if sublime.yes_no_cancel_dialog(_wrap(
36 | """
37 | Force a HyperHelp bootstrap?
38 |
39 | This will execute a bootstrap and replace the existing
40 | HyperHelp system package (if any) with a newly generated
41 | one.
42 | """)) == sublime.DIALOG_YES:
43 | log("Developer: Forcing a bootstrap")
44 | BootstrapThread().start()
45 |
46 | def is_enabled(self):
47 | return _is_developer_mode()
48 |
49 |
50 | ###----------------------------------------------------------------------------
51 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/events.py:
--------------------------------------------------------------------------------
1 | import sublime
2 | import sublime_plugin
3 |
4 | from collections import MutableSet
5 |
6 | from hyperhelpcore.common import log
7 | from hyperhelpcore.core import help_index_list, lookup_help_topic
8 | from hyperhelpcore.core import is_topic_file, is_topic_file_valid
9 | from hyperhelpcore.core import is_topic_url
10 | from hyperhelpcore.view import find_help_view
11 | from hyperhelpcore.help import _get_link_topic
12 |
13 | from hyperhelpcore.core import load_indexes_from_packages
14 | from hyperhelpcore.core import unload_help_indexes_from_packges
15 |
16 |
17 | ###----------------------------------------------------------------------------
18 |
19 |
20 | _help_popup = """
21 |
22 |
45 | {body}
46 |
47 | """
48 |
49 | _missing_pkg = """
50 | Package not found
51 | This link references a help package that is
52 | not currently installed.
53 | {pkg} / {topic}
54 | """
55 |
56 | _missing_topic = """
57 | Topic not found
58 | This link references a topic that does not appear
59 | in the help index.
60 | {pkg} / {topic}
61 | """
62 |
63 | _missing_file = """
64 | Package File not found
65 | This link opens a package file that does not
66 | currently exist.
67 | {file}
68 | """
69 |
70 |
71 | _topic_body = """
72 | {title}
73 | {link_type}
74 | {link}
75 | """
76 |
77 |
78 | ###----------------------------------------------------------------------------
79 |
80 |
81 | class PackageIndexWatcher():
82 | """
83 | A simple singleton class for determining when packages are being added to
84 | or removed from the list of ignored packages, so that we can trigger help
85 | indexes in those packages to be either unloaded or loaded, as needed.
86 | """
87 | instance = None
88 |
89 | def __init__(self):
90 | if PackageIndexWatcher.instance is not None:
91 | return
92 |
93 | PackageIndexWatcher.instance = self
94 | self.settings = sublime.load_settings("Preferences.sublime-settings")
95 | self.cached_ignored = set(self.settings.get("ignored_packages", []))
96 |
97 | self.settings.add_on_change("_hh_sw", lambda: self.__setting_changed())
98 |
99 | @classmethod
100 | def unregister(cls):
101 | if PackageIndexWatcher.instance is not None:
102 | PackageIndexWatcher.instance.settings.clear_on_change("_hh_sw")
103 | PackageIndexWatcher.instance = None
104 |
105 |
106 | def __setting_changed(self):
107 | new_list = set(self.settings.get("ignored_packages", []))
108 | if new_list == self.cached_ignored:
109 | return
110 |
111 | removed = self.cached_ignored - new_list
112 | added = new_list - self.cached_ignored
113 | self.cached_ignored = new_list
114 |
115 | if added:
116 | log("unloading all help indexes loaded from: %s", list(added))
117 | sublime.set_timeout(lambda: unload_help_indexes_from_packges(list(added)), 2000)
118 |
119 | if removed:
120 | log("scanning for help indexes in: %s", list(removed))
121 | sublime.set_timeout(lambda: load_indexes_from_packages(list(removed)), 2000)
122 |
123 |
124 | ###----------------------------------------------------------------------------
125 |
126 |
127 | def plugin_loaded():
128 | PackageIndexWatcher()
129 | for window in sublime.windows():
130 | view = find_help_view(window)
131 | if view:
132 | view.run_command("hyperhelp_internal_flag_links")
133 |
134 |
135 | def plugin_unloaded():
136 | PackageIndexWatcher.unregister()
137 |
138 |
139 | def _show_popup(view, point, popup):
140 | view.show_popup(
141 | _help_popup.format(body=popup),
142 | flags=sublime.HIDE_ON_MOUSE_MOVE_AWAY,
143 | location=point,
144 | max_width=1024)
145 |
146 |
147 | ###----------------------------------------------------------------------------
148 |
149 |
150 | class HyperhelpEventListener(sublime_plugin.EventListener):
151 | def on_text_command(self, view, command, args):
152 | """
153 | Listen for the drag_select command with arguments that tell us that the
154 | user double clicked, see if they're double clicking on a link so we
155 | know if we should try to follow it or not.
156 | """
157 | if (view.is_read_only() and command == "drag_select" and
158 | args.get("by", None) == "words"):
159 | event = args["event"]
160 | point = view.window_to_text((event["x"], event["y"]))
161 |
162 | if view.match_selector(point, "text.hyperhelp meta.link"):
163 | view.window().run_command("hyperhelp_navigate",
164 | {"nav": "follow_link"})
165 | return ("noop")
166 |
167 | return None
168 |
169 |
170 | def on_hover(self, view, point, hover_zone):
171 | """
172 | When the mouse hovers over a link in a help view, show a popup that
173 | tells you where the link goes or what file/URL it opens.
174 | """
175 | if hover_zone != sublime.HOVER_TEXT:
176 | return
177 |
178 | default_pkg = view.settings().get("_hh_pkg", None)
179 | if default_pkg is None or not view.score_selector(point, "meta.link"):
180 | return
181 |
182 | link_info = _get_link_topic(view, view.extract_scope(point))
183 | if link_info is None:
184 | return
185 |
186 | pkg = link_info.get("pkg", default_pkg)
187 | topic = link_info.get("topic")
188 |
189 | # Report if we don't know the package. In this case we may know what
190 | # the topic is but not what file it might appear in.
191 | pkg_info = help_index_list().get(pkg, None)
192 | if pkg_info is None:
193 | popup = _missing_pkg.format(pkg=pkg, topic=topic)
194 | return _show_popup(view, point, popup)
195 |
196 | # If there is no topic we can't really display anything useful. This is
197 | # an exceptional situation that is only possible if the help is broken.
198 | if topic is None:
199 | return
200 |
201 | # Look up the topic details. If we can't find it in the index, react
202 | # like a missing package since we can't know the file.
203 | topic_data = lookup_help_topic(pkg_info, topic)
204 | if topic_data is None:
205 | popup = _missing_topic.format(pkg=pkg, topic=topic)
206 | return _show_popup(view, point, popup)
207 |
208 | caption = topic_data.get("caption")
209 | file = topic_data.get("file")
210 | link = file
211 |
212 | # For links that open files, if that file does not exist as far as
213 | # Sublime is concerned, use a custom popup to let the user know. Such
214 | # a link will be highlighted as broken, so this explains why.
215 | #
216 | # This returns None for things that are not package files, so we need
217 | # to compare for False directkly.
218 | if is_topic_file_valid(pkg_info, topic_data) is False:
219 | popup = _missing_file.format(file=file)
220 | return _show_popup(view, point, popup)
221 |
222 | if is_topic_url(pkg_info, topic_data):
223 | link_type = "Opens URL: "
224 | elif is_topic_file(pkg_info, topic_data):
225 | link_type = "Opens File: "
226 | else:
227 | link_type = "Links To: "
228 |
229 | link = "" if default_pkg == pkg else pkg + " / "
230 |
231 | current_file = view.settings().get("_hh_file", None)
232 | if file != current_file:
233 | link = link + file + " / "
234 |
235 | link = link + topic
236 |
237 | popup = _topic_body.format(title=caption or topic,
238 | link_type=link_type,
239 | link=link)
240 |
241 | _show_popup(view, point, popup)
242 |
243 |
244 | ###----------------------------------------------------------------------------
245 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/help/api.txt:
--------------------------------------------------------------------------------
1 | %hyperhelp title="HyperHelp API" date="2019-03-23"
2 |
3 |
4 | # API Overview
5 | ==================
6 |
7 | HyperHelp provides several |commands|, |key contexts| and an api that allow you
8 | to customize the help experience for yourself or for users of your package by
9 | creating your own custom key bindings, menu entries or plugins.
10 |
11 | Since HyperHelp (more specifically |hyperhelpcore|, which provides the API) is
12 | still under active development and subject to change without notice, the API is
13 | not yet documented.
14 |
15 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/help/authoring.txt:
--------------------------------------------------------------------------------
1 | %hyperhelp title="HyperHelp: Authoring Help" date="2019-03-25"
2 |
3 |
4 | # Authoring Overview
5 | ====================
6 |
7 | HyperHelp is designed to make the barrier to entry as easy as possible in order
8 | to get help up and running. In order to create help for your package, you need
9 | to author:
10 |
11 | * A |hyperhelp.json| file to act as a help index file. This file tells
12 | HyperHelp what files in your package represent help files, and what
13 | topics appear in each file.
14 |
15 | As the name suggests, this is a |JSON| file; HyperHelp uses the internal
16 | JSON loader in Sublime, which is less strict than standard JSON and
17 | allows for comments, which can be of help in documenting your index.
18 |
19 | * One or more |help files| to provide the actual help content. These are
20 | regular text files which can make use of some simple |markup| to define
21 | the navigation elements in the file as well as some simple visual
22 | styling. There are some |:style.txt:style guidelines| to follow in your help files
23 | to ensure that everything is consistent for users.
24 |
25 | This help includes an |example hyperhelp.json| file and an |example index.txt|
26 | help file that demonstrate a simplistic help system and how everything ties
27 | together.
28 |
29 | Although you can create the needed files manually if desired, the
30 | |HyperHelpAuthor| package allows for easy creation of help indexes and files by
31 | doing some of the heavy lifting for you.
32 |
33 | `NOTE:` Like HyperHelp itself, HyperHelpAuthor is still under active
34 | development, so not all planned features exist yet.
35 |
36 | Once you have |:integration.txt:integrated| HyperHelp in your package and authored help, your
37 | job is done; HyperHelp will automatically find and present your help files to
38 | the user with no further setup.
39 |
40 |
41 | # Help Index Loading
42 | ====================
43 |
44 | When the HyperHelp package loads, it scans the package directory for all of the
45 | |hyperhelp.json| files that exist, and loads them all in order to determine
46 | what help is currently available. These index files contain all of the meta
47 | information needed to know what packages contain help, and what that help
48 | consists of.
49 |
50 | In addition, as packages move in and out of the `ignored_packages` setting,
51 | any help indexes they contain will be either loaded or unloaded to keep the
52 | help information current.
53 |
54 | Note that it's possible for one physical package to contain multiple logical
55 | help packages within itself. Each index is treated as a separate package and
56 | presented as such. The |SnAPI| package that displays the official Sublime Text
57 | help is an example of this.
58 |
59 |
60 | # Navigating Topics
61 | ===================
62 |
63 | HyperHelp navigates help topics by looking up a |topic| in the index in order
64 | to determine what help file needs to be displayed. In order to do this, two
65 | pieces of information are required:
66 |
67 | * The help `topic` to view
68 | * The help `package` that the topic should be looked up in
69 |
70 | When no package is provided, the package whose help is currently being
71 | displayed is used by default. Similarly, if no help topic is provided, it is
72 | assumed to be `index.txt`.
73 |
74 | By looking up the help topic in the index for the appropriate package,
75 | HyperHelp can determine what help file it needs to display in the |help view|.
76 | Once that file is displayed, the |anchor| that matches the topic is found and
77 | focused.
78 |
79 | Based on this, some rules apply:
80 |
81 | * Only |help files| that appear in their package's help index can be opened
82 | and displayed because otherwise HyperHelp does not know where they are.
83 |
84 | * |:topic:Topics| within a help package must be unique; if there is more than one
85 | identical topic, HyperHelp is unable to determine which one to display.
86 |
87 | * An |anchor| must be present in a help file that matches the topic;
88 | otherwise once the help file is opened, HyperHelp can't know where in the
89 | file to look.
90 |
91 | By convention, all |help files| contain a |file header| which provides
92 | information on the title and last modification date of that particular file.
93 | When the help file is rendered, it contains an implicit anchor that specifies
94 | the name of the help file itself.
95 |
96 | This makes it possible to navigate to any help file in any package by using
97 | it's name as a help topic.
98 |
99 | Based on this convention and the fact that the default topic is `index.txt`
100 | when one is not provided, all help packages should contain an `index.txt` help
101 | file that specifies the entry point to the help in much the same way as the
102 | `index.html` file does for a folder on a web page.
103 |
104 | This allows a convenient way to open the help for any package by merely
105 | specifying that you which to browse that package directly.
106 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/help/bookmarks.txt:
--------------------------------------------------------------------------------
1 | %hyperhelp title="HyperHelp Bookmarks" date="2019-03-23"
2 |
3 |
4 | # Bookmarks
5 | ===========
6 |
7 | HyperHelp allows you to create bookmarks for help topics that you often use,
8 | allowing you to jump back to them at any point. From within a |help view| you
9 | can create a bookmark by pressing or jump to an existing bookmark by
10 | pressing .
11 |
12 | The command palette command `HyperHelp: Open Bookmarked Help Topic` is also
13 | available from any view, and will navigate to a bookmarked help topic, creating
14 | the help view if it doesn't already exist.
15 |
16 |
17 | # Creating Bookmarks
18 | --------------------
19 |
20 | When you invoke the command to create a bookmark, HyperHelp will prompt you to
21 | provide details on the bookmark to create; it's `type` and it's `name`.
22 |
23 | The `type` of the bookmark determines what happens when you navigate to that
24 | particular bookmark, while the `name` determines how it is displayed in the
25 | bookmark list.
26 |
27 |
28 | ## File Bookmark
29 | ----------------
30 |
31 | A `file` bookmark bookmarks the file that you're currently viewing in the
32 | |help view|. When you navigate back to this bookmark, the cursor will be
33 | placed at the |anchor| in the |header| of the file after it's loaded.
34 |
35 | This is useful to bookmark a general help file, such as a reference
36 | document.
37 |
38 |
39 | ## View Bookmark
40 | ----------------
41 |
42 | A `view`bookmark bookmarks the current state of the |help view|. When you
43 | navigate back to this bookmark later, not only will the file open but the
44 | cursor and viewport will be put back into the exact same state as they were
45 | when the bookmark was created.
46 |
47 | This is useful to take a snapshot of the help before leaving to do other
48 | things and still being able to find your way back to where you left off.
49 |
50 |
51 | ## Topic Bookmark
52 | -----------------
53 |
54 | A `topic` bookmark is like a `file` bookmark, except that where the `file`
55 | bookmark creates a bookmark that opens a particular file, a `topic`
56 | bookmark bookmarks a specific topic instead.
57 |
58 | This type of bookmark is context sensitive; in order to be given this
59 | option for your bookmark, the cursor needs to be placed on top of a link to
60 | that topic first.
61 |
62 | HyperHelp supports three different kinds of bookmarks that allow you to create
63 | a bookmark
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/help/changelog.txt:
--------------------------------------------------------------------------------
1 | %hyperhelp title="HyperHelp ChangeLog" date="2020-04-06"
2 |
3 |
4 | ## latest_update:Version 0.0.8 (2020-04-06)
5 | -------------------------------
6 |
7 | * This introduces a new setting `focus_links_at_top`. This controls where the
8 | anchor of a link is focused in the window when you follow one. The default
9 | value is `true`, which forces the link anchor to the top of the window (as
10 | a traditional browser would).
11 |
12 | To get the legacy behaviour of centering the link in the window, set this
13 | to `false`.
14 |
15 | Note that this does not affect using the key to navigate between the
16 | anchors in a help file.
17 |
18 |
19 | ## _none:Version 0.0.7 (2019-10-31)
20 | -------------------------------
21 |
22 | * On install or upgrade, the HyperHelp system package will now display
23 | either the `changelog.txt` file or the `help_on_help.txt` file, so
24 | that you either learn how to use the help system or see what is new.
25 |
26 | The new setting `show_changelog` controls whether this is active or
27 | not; it defaults to `True`.
28 |
29 |
30 | ## _none:Version 0.0.6 (2019-10-31)
31 | -------------------------------
32 |
33 | * This changelog file now exists to indicate the version history of the
34 | package over time. The help index, command palette and the main menu can
35 | all be used to navigate to the file.
36 |
37 | * The |dependency settings| have been changed to use a prefix of `hyperhelp.`
38 | instead of `hyperhelp_`, as |PackageDev| syntax highlights that format
39 | directly. In addition, a hint file was added so that PackageDev can show
40 | you default values and auto-complete the settings directly.
41 |
42 | * The commands that create and navigate to bookmarks from the command palette
43 | have been modified to use the `show_overlay` command rather than invoking
44 | the command directly.
45 |
46 |
47 | ## _none:Version 0.0.5 (2019-03-31)
48 | -------------------------------
49 |
50 | * Include a command to display the package version of the bootstrapped
51 | package and of the dependency in preparation for the initial public
52 | announcement on April 1.
53 |
54 |
55 | ## _none:Version 0.0.4 (2019-03-27)
56 | -----------------------------
57 |
58 | * Bump the internal version number which was accidentally skipped from the
59 | 0.0.3 release, stopping existing installs from seeing the changes.
60 |
61 |
62 | ## _none:Version 0.0.3 (2019-03-25)
63 | -----------------------------
64 |
65 | * Enhance key contexts used in key bindings
66 |
67 | * Ensure that when the history index panel is opened, the current help item
68 | is initially selected.
69 |
70 | * While post processing, removal of comments would also remove comments from
71 | in-line code blocks; this has been fixed.
72 |
73 | * Rewrite the internal help to be more up to date with how the package has
74 | been rewritten in the last year.
75 |
76 |
77 | ## _none:Version 0.0.2 (2019-03-07)
78 | -----------------------------
79 |
80 | * Watch `ignored_packages` to determine when packages are being ignored or
81 | unignored and load or drop their indexes as needed to keep help in sync
82 | with packages.
83 |
84 | * Fix a bug in bootstrapping that would block it from happening if the
85 | package was unpacked.
86 |
87 |
88 | ## _none:Version 0.0.1 (2019-02-17)
89 | -----------------------------
90 |
91 | * Initial release
92 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/help/commands.txt:
--------------------------------------------------------------------------------
1 | %hyperhelp title="HyperHelp Commands" date="2019-03-23"
2 |
3 |
4 | # Command Overview
5 | ==================
6 |
7 | HyperHelp provides several commands, |key contexts| and an |api| that allow you
8 | to customize the help experience for yourself or for users of your package by
9 | creating your own custom key bindings, menu entries or plugins.
10 |
11 | The commands listed here expose the core of the HyperHelp commands for the most
12 | common tasks. For more complex operations, the |api| may be able to help.
13 |
14 |
15 | ## hyperhelp_topic
16 | ------------------
17 |
18 | Arguments: `package`
19 | `topic`
20 |
21 | Navigate the current |help view| to the provided topic in the given package,
22 | creating a new help view if the current window does not already have one.
23 |
24 | When there is an existing help view, the `package` argument can be omitted and
25 | will default to the package currently being displayed. Similarly if the topic
26 | is missing, the default is `index.txt`. This allow this command to open any
27 | help package without having to know the name of a file that it contains.
28 |
29 | This command is always available, but will display an error in the status line
30 | if it cannot display the given help topic for any reason, such as if the topic
31 | does not appear in the index for the given package or the package cannot be
32 | found.
33 |
34 |
35 | ## hyperhelp_contents
36 | ---------------------
37 |
38 | Arguments: `package`
39 | `prompt`
40 |
41 | This command will display the |table of contents| for the help package given.
42 | If no package is provided, but there is currently a |help view| visible, the
43 | table of contents for the visible package is displayed.
44 |
45 | When `prompt` is `true` or no `package` was given and one cannot be inferred
46 | from an existing help view, you will be prompted to select the help package
47 | whose table of contents you wish to view.
48 |
49 | This command is unavailable if no `package` is provided, there is no current
50 | help view, and `prompt` is set to `False`. This allows key bindings and menu
51 | entries to not be available if there is no help view available to provide a
52 | package.
53 |
54 | In order to ensure that this command is always enabled, ensure that you pass a
55 | value of `true` to the `prompt` argument.
56 |
57 |
58 | ## hyperhelp_index
59 | ------------------
60 |
61 | Arguments: `package`
62 | `prompt`
63 |
64 | This command will display the |topic| index for the help package given. If no
65 | package is provided, but there is currently a |help view| visible, the index
66 | for the visible package is displayed.
67 |
68 | When `prompt` is `true` or no `package` was given and one cannot be inferred
69 | from an existing help view, you will be prompted to select the help package
70 | whose index you wish to view.
71 |
72 | The index is a list of every known topic in every known help file within the
73 | given package, which allows you to quickly find and select a topic without
74 | knowing where it's located.
75 |
76 | This command is unavailable if no `package` is provided, there is no current
77 | help view, and `prompt` is set to `False`. This allows key bindings and menu
78 | entries to not be available if there is no help view available to provide a
79 | package.
80 |
81 | In order to ensure that this command is always enabled, ensure that you pass a
82 | value of `true` to the `prompt` argument.
83 |
84 |
85 | ## hyperhelp_navigate
86 | ---------------------
87 |
88 | Arguments: `nav`
89 | Possible values of this argument are:
90 | `find_anchor`
91 | `follow_link`
92 | `prev`
93 |
94 | This command is the core of navigating within help files in HyperHelp. The
95 | following types of navigation are available, based on the value of the `nav`
96 | command line argument:
97 |
98 | `find_anchor` will shift the cursor to the next or previous |anchor| within
99 | the current help view, wrapping around the ends of the file if needed.
100 |
101 | `follow_link` will navigate to the topic represented by the link that is
102 | currently under the first cursor in the |help view|, if there is one. If
103 | the cursor is not currently on a link, this does nothing.
104 |
105 | This command is only available when there is a help view visible in the current
106 | window and the value of the `nav` argument is one of the valid values.
107 |
108 |
109 | ## hyperhelp_history
110 | --------------------
111 |
112 | Arguments: `action`
113 | Possible values of this argument are:
114 | `next`
115 | `prev`
116 | `jump`
117 | `clear`
118 | `index`
119 | This argument is only used when `action` is `jump`.
120 |
121 | This command allows for navigation within the history that each |help view|
122 | records as the user navigates through help topics.
123 |
124 | The action taken depends on the value provided in the `action` argument:
125 |
126 | `next` and `prev` will navigate to the next or previous item in the history
127 | for the current help view; this navigation will return the cursor location
128 | and viewport back to what it was at the time the history entry was created.
129 |
130 | `clear` will clear the entire history of the current help view. This puts
131 | the help view back into the state it was in when it was originally created.
132 |
133 | `jump` will jump the history to the `index` given (if possible). When the
134 | `index` value is `-1` (the default) or when the index is out of bounds for
135 | the number of history items that exist in the help view, the command will
136 | visualize the history for the user to allow them to select the appropriate
137 | history entry themselves.
138 |
139 | This command is only available when there is a help view in the current window
140 | and the value of the `action` argument is one of the valid values. In addition,
141 | the command is not available when the command makes no sense to execute, such
142 | as trying to go back when you're on the first history entry already or clearing
143 | the history when it's empty.
144 |
145 |
146 | ## hyperhelp_current_help
147 | -------------------------
148 |
149 | Arguments: `help_fmt`
150 | `no_help_fmt`
151 |
152 | This command does nothing and is always disabled. If used as a command in a
153 | menu item, the caption will tell you the name of the package that help is
154 | currently being displayed for, if any.
155 |
156 | The provided arguments provide the text to use in either case, allowing you to
157 | customize the text used if desired.
158 |
159 |
160 | ## hyperhelp_create_bookmark
161 | ----------------------------
162 |
163 | Arguments: `name`
164 | `package`
165 | `topic`
166 | `caret`
167 | `viewport`
168 |
169 | `NOTE:` This command does not validate that the arguments that you are
170 | providing make sense. The |hyperhelp_prompt_create_bookmark|
171 | command will create a bookmark after prompting the user.
172 |
173 | This command will create a bookmark using the provided properties; the bookmark
174 | will use the given `name` and will be to the `topic` given in the `package`
175 | provided.
176 |
177 | In addition, `caret` is an array of two numbers that represent a selection
178 | region in the file while `viewpoert` is an array of two numbers that represents
179 | a viewport position.
180 |
181 | These arguments are optional, and can be used to specify the initial selection
182 | in the help file and what portion of it should be focused. When they're not
183 | provided, the help topic is navigated to as per usual.
184 |
185 | Since this command unconditionally creates a bookmark, it is always available.
186 |
187 |
188 | ## hyperhelp_prompt_create_bookmark
189 | ------------------------------------
190 |
191 | Arguments: None
192 |
193 | This command will prompt the user to create a bookmark by asking for the
194 | details of the new bookmark to be created. The prompts are based on the state
195 | of the current help view, and allow the user to customize them before commiting
196 | to the creation.
197 |
198 | This command is only available in windows that have an existing |help view|. If
199 | you need to create a bookmark when there is no help view open, you can view the
200 | appropriate help topic first or use |hyperhelp_create_bookmark| to directly
201 | create the appropriate bookmark.
202 |
203 |
204 | ## hyperhelp_open_bookmark
205 | --------------------------
206 |
207 | Arguments: `bookmark_idx`
208 |
209 | This command will navigate the user directly to the bookmark at the provided
210 | bookmark index, if possible. Nothing will occur if the bookmark index is out of
211 | range, including when there are no bookmarks to navigate to.
212 |
213 | If no bookmark index is provided, the user is prompted to select the
214 | appropriate bookmark before the navigation happens.
215 |
216 | This command is always available; if there is no current |help view|, one will
217 | be created when the user selects the bookmark to open.
218 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/help/example.txt:
--------------------------------------------------------------------------------
1 | %hyperhelp title="Help Examples" date="2019-03-25"
2 |
3 |
4 | # Example hyperhelp.json
5 | ------------------------
6 |
7 | This is an example help index for a package containing a single help file. The
8 | metadata at the top instructs HyperHelp that this is the index for a package
9 | named `Sample`, and that inside of that package, the help files (i.e.
10 | `index.txt`) are inside of a folder named `help/`.
11 |
12 | The topics in a single file are declared, along with captions and aliases. In
13 | addition some externals are also defined to open the `exec.py` file in the
14 | default package and the home page for `hyperhelpcore` itself.
15 |
16 | The `help_contents` provides a simple hierarchical table of contents that lets
17 | you jump to the top level of the file and also sections. This also demonstrates
18 | overriding the captions for some items.
19 |
20 |
21 | ```json
22 | {
23 | "package": "Sample",
24 | "description": "Help for Sample Package",
25 | "doc_root": "help/",
26 |
27 | "help_files": {
28 | "index.txt": [
29 | "Index file for Sample package",
30 |
31 | {
32 | "topic": "index.txt",
33 | "caption": "Index file",
34 | "aliases": ["index file"]
35 | },
36 | {
37 | "topic": "introduction",
38 | "caption": "Introduction Section"
39 | },
40 | {
41 | "topic": "anchor",
42 | "caption": "Sample Anchor"
43 | },
44 | {
45 | "topic": "section two",
46 | "caption": "Second Section"
47 | },
48 | {
49 | "topic": "hidden anchor",
50 | "caption": "An anchor that is not visible in the document"
51 | },
52 | {
53 | "topic": "section three",
54 | "caption": "The third and last section"
55 | },
56 | ]
57 | },
58 |
59 | "externals": {
60 | "Packages/Default/exec.py": [
61 | "The exec plugin",
62 |
63 | {
64 | "topic": "exec.py",
65 | },
66 | ],
67 |
68 | "https://github.com/STealthy-and-haSTy/hyperhelpcore": [
69 | "The HyperHelp core dependency",
70 |
71 | {
72 | "topic": "hyperhelpcore",
73 | "caption": "Core Dependency"
74 | },
75 | ]
76 |
77 | },
78 |
79 | "help_contents": [
80 | "index.txt",
81 | {
82 | "topic": "index.txt",
83 | "caption": "The Sections",
84 | "children": [
85 | {
86 | "topic": "introduction",
87 | "caption": "Section One"
88 | },
89 | "section two",
90 | "section three"
91 | ]
92 | },
93 | ]
94 | }
95 | ```
96 |
97 |
98 | # Example index.txt
99 | -------------------
100 |
101 | This is the help file that goes with the sample above. It should be placed in
102 | the same package as the above index, in a folder named `help/` (or you can
103 | change the |doc_root| in the sample to suit).
104 |
105 | This shows some of the simpler |markup| elements, such as |anchors|, |links|
106 | and |:headings:section headings|.
107 |
108 |
109 | ```help
110 | %hyperhelp title="Index file for Sample package" date="2019-03-22"
111 |
112 | This is the root help file for the 'Sample' package.
113 |
114 | If you use `Goto > Goto Symbol` in the main menu, the symbol list will show you
115 | the section heading, indented based on the level of the section header itself.
116 | You can also press and to jump back and forth between the
117 | sections.
118 |
119 | Follow links by double clicking on them or pressing while the cursor is
120 | on them.
121 |
122 |
123 | # Introduction
124 | --------------
125 |
126 | This part of the file would be a simple introduction. It also has an inline
127 | *anchor* for a link to jump to.
128 |
129 |
130 | ## Section Two
131 | --------------
132 |
133 | This is a second section in the sample file. Along with a link to the |anchor|
134 | in the previous section, this also contains a *|hidden anchor|*, which
135 | functions the same as a regular one but is not visible in the document.
136 |
137 |
138 | ### Section Three
139 | -----------------
140 |
141 | This is the third section. Apart from being here to show that three levels of
142 | section header are possible, it also shows that you can link to a |hidden
143 | anchor| the same as a regular one.
144 |
145 | In addition, you can also open the |exec.py| plugin by following this link or
146 | view the code for |hyperhelpcore|, the dependency that powers HyperHelp.
147 | ```
148 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/help/help_index.txt:
--------------------------------------------------------------------------------
1 | %hyperhelp title="Help Index Files" date="2019-03-23"
2 |
3 |
4 | # hyperhelp.json:The hyperhelp.json file
5 | =========================
6 |
7 |
8 | Every package which contains help must include a `hyperhelp.json` file which
9 | provides all of the meta information to allow HyperHelp to know what help is
10 | available in that particular package.
11 |
12 | The name of the file is important; HyperHelp only looks specifically for files
13 | with the name `hyperhelp.json`. As the name suggests, the file is a |JSON|
14 | formatted file, with a schema that outlines all of the information that
15 | HyperHelp needs in order to present the help.
16 |
17 | The sections below specify the structure of the index as a series of keys that
18 | can be used and what they are used for. See the |example hyperhelp.json| file
19 | for a complete example of a minimal help index; you can use this as a starting
20 | point for your own help index if you're not using |HyperHelpAuthor| to author
21 | your help files.
22 |
23 |
24 | ## Package Description
25 | ----------------------
26 |
27 | These keys are used in the `hyperhelp.json` file to tell HyperHelp how to
28 | present the help in this index file to the user and what files it contains.
29 | With the exception of the `package` key, all of these keys are optional;
30 | you only need to specify them when you want to override the default value.
31 |
32 | *package* `[REQUIRED]`
33 |
34 | The name of the package that this help index is for. This does not need
35 | to be the same as the physical package that the index is stored inside;
36 | for example if you are creating a package that contains help for some
37 | other package.
38 |
39 | If multiple index files present themselves as being the help for the
40 | same package, one index will be selected as the one to use. The index
41 | stored in the physical package of the same name is chosen as the
42 | canonical index and used; otherwise the last loaded index is used
43 | instead.
44 |
45 |
46 | *description*
47 |
48 | The human readable description of the help in this package. This is
49 | presented to the user in places where they are allowed to select a
50 | help package, such as when using `HyperHelp: Browse Available Help`.
51 |
52 | If this key is not present, a default value is used:
53 |
54 | ```json
55 | "description": "Help for PackageName"
56 | ```
57 |
58 |
59 | *doc_root*
60 |
61 | A relative path inside of the package containing the index file that
62 | indicates where the help files for this package are located. When this
63 | is not specified, the default is to assume that the help files are
64 | stored alongside the index.
65 |
66 |
67 | *default_caption*
68 |
69 | The default caption to apply to a |:help topics:help topic| that doesn't have one
70 | explicitly defined. This is a string which can contain the placeholder
71 | values `{topic}`, `{source}` and `{package}` to indicate the help
72 | topic, source help file and containing package, respectively.
73 |
74 | When this is not provided, the following default is used:
75 |
76 | ```json
77 | "default_caption": "Topic {topic} in help source {source}"
78 | ```
79 |
80 |
81 | ## help_files:Package Help Files
82 | ---------------------
83 |
84 | The top level key `help_files` is used to specify the list of help files
85 | that make up the help in this help index. The value is a dictionary in
86 | which the keys are the names of help files and the values are lists of help
87 | topics that exist in that help file.
88 |
89 | The contents of this key and the |externals| key are used to collate the
90 | complete list of all help topics that exist within the help package, and by
91 | extension in what file those help topics can be found.
92 |
93 | Help files that don't appear here as well as help topics that aren't listed
94 | in their related file cannot be viewed or loaded. |HyperHelpAuthor|
95 | contains linting tools to ensure that all help topics and files in a
96 | package are addressable.
97 |
98 | ```json
99 | "help_files": {
100 | "index.txt": [ /* help topics */ ],
101 | "other.txt": [ /* help topics */ ],
102 | }
103 | ```
104 |
105 |
106 | ### Help Topics
107 |
108 | Each help file listed in the |help_files| key is a JSON list that
109 | contains all of the help topics contained within that particular help
110 | file.
111 |
112 | In this list, the first item must be a string which represents the
113 | title of the help file itself; this is used to display the name of the
114 | help file itself in various places.
115 |
116 | Every help file in a help package is an implicit topic which uses the
117 | title of the help file as the caption, and every rendered help file
118 | includes an |anchor| in the header line that represents the file name.
119 | Thus, all help files are readily addressable by name.
120 |
121 | The remainder of the items in the list are a list of dictionaries which
122 | represent each topic which is contained in that file.
123 |
124 | *topic* `[REQUIRED]`
125 |
126 | A string which represents a help topic that can be found in this
127 | help file. Help topics must be unique within a single package. In
128 | addition, the help file should have an |anchor| that matches this
129 | topic, or the user will be unable to navigate there.
130 |
131 | `NOTE:` Topics that begin with leading underscores are reserved for
132 | use by HyperHelp itself (see for example the `_none` topic
133 | as outlined in the |markup| section on |:anchor:anchors|).
134 |
135 | In addition, due to the syntax of |anchors| and |links|, a
136 | `:` character is not allowed in a topic (although it can
137 | appear in the anchor or link text).
138 |
139 | *caption*
140 |
141 | A textual caption for this particular topic. This is used in places
142 | where the user is prompted to select a help topic, such as in the
143 | |table of contents|.
144 |
145 | When no caption is provided for a help topic, the |default_caption|
146 | is applied instead.
147 |
148 |
149 | *aliases*
150 |
151 | A list of other topic aliases that represent this particular topic.
152 | This allows you to associate multiple potential topics to a single
153 | topic in cases where that makes logical sense.
154 |
155 | Aliases share the same namespace as topics, and as such must also
156 | be unique amongst all other topics and aliases within the same
157 | help package.
158 |
159 |
160 | ```json
161 | "help_files": {
162 | // This help file contains two topics; one implicitly defined by
163 | // its file name and one explicit topic. In addition, the explicit
164 | // topic is also known by an alias.
165 | "index.txt": [
166 | "Title of the Index File",
167 |
168 | {
169 | "topic": "sample topic",
170 | "caption": "The sample topic in index.txt",
171 | "aliases": ["sample"]
172 | }
173 | ]
174 | }
175 | ```
176 |
177 |
178 | ### External Resources
179 | ----------------------
180 |
181 | In addition to standard help files, HyperHelp can also automatically
182 | open package files and web URLs through the use of `externals`. This
183 | allows you the freedom to do things such as open other resource files
184 | (e.g. a README file) as well as link to external web documentation as
185 | needed.
186 |
187 | *externals*
188 |
189 | This key operates similar to the |help_files| key, except that
190 | where that key specifies the names of help files, this key
191 | specifies the names of external resources.
192 |
193 | As in that key, every external is implicitly defined as a topic
194 | with it's title as a caption. In addition, any topics inside of
195 | an external definition are implicit aliases and will share the
196 | same caption unless one is specified.
197 |
198 | ```json
199 | "externals": {
200 | // An external to open my home page. This defines a topic that is
201 | // the explicit URL with a caption of "OdatNurd's Home Page". It
202 | // also defines a topic named "homepage" with a caption of "My
203 | // Homepage". Either topic will result in the web page being
204 | // opened.
205 | "https://odatnurd.net/": [
206 | "OdatNurd's Home Page",
207 |
208 | {
209 | "topic": "homepage",
210 | "caption": "My Homepage"
211 | }
212 | ],
213 |
214 | // An external to open a package file. As above, there are two
215 | // topics defined here; one that is the package file name and one
216 | // that is just "exec.py". This time both have the same caption.
217 | // Both will open the package file.
218 | "Packages/Default/exec.py": [
219 | "The default exec command",
220 |
221 | {
222 | "topic": "exec.py"
223 | }
224 | ]
225 | }
226 | ```
227 |
228 |
229 | ### Table of Contents
230 | ---------------------
231 |
232 | Every help index can define a custom table of contents via the
233 | `help_contents` key if desired, to allow the user to see and browse the
234 | help in a hierarchy defined by the help author. If this key is not
235 | present in the help index, a table of contents is generated
236 | automatically by gathering every help topic contained in the packge.
237 |
238 | *help_contents*
239 |
240 | This key specifies a list of help topics which should be presented
241 | to the user when they open the table of contents (by default this
242 | is done via the > key). The table of contents is presented as a
243 | structured list of help topics, and displays the topic captions for
244 | clarity.
245 |
246 | For simplicity, items in the list can be strings that represent
247 | help topics. This will perform a lookup of the topic and use that
248 | to infer the caption to use.
249 |
250 | For more control items in the list can also be |:help topics:topic dictionaries|
251 | as well. In this case the topics must already exist, but the
252 | caption used can be altered.
253 |
254 | The *children** key can be used in topic dictionaries contained in
255 | the `help_contents` in order to specify that when selected this
256 | topic should present a list of other related help topics in a
257 | hierarchy. This allows for more complex contents without making the
258 | list overwhelming.
259 |
260 | ```json
261 | // This table of contents specifies four top level items. The first
262 | // two topics use their default captions and the third has a custom
263 | // caption. The "options.txt" topic presents a list of three child
264 | // topics, with the last one having a custom caption.
265 | "help_contents": [
266 | "index.txt",
267 | "syntax.txt",
268 | {
269 | "topic": "other.txt",
270 | "caption": "Replaced Caption"
271 | },
272 | {
273 | "topic": "options.txt",
274 | "children": [
275 | "option1",
276 | "option2",
277 | {
278 | "topic": "option3",
279 | "caption": "Customized Option 3 Caption"
280 | }
281 | ]
282 | }
283 |
284 | ]
285 | ```
286 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/help/help_on_help.txt:
--------------------------------------------------------------------------------
1 | %hyperhelp title="How to use HyperHelp" date="2019-03-25"
2 |
3 |
4 | # Introduction
5 | ==============
6 |
7 | HyperHelp is a Sublime Text package that provides a simple text based, context
8 | sensitive help system for Sublime Text 3. Using HyperHelp, package authors can
9 | easily provide interactive help for their packages in a consistent way.
10 |
11 | Using HyperHelp, any package in Sublime Text can contain help, which includes
12 | not only third party packages but also your own `User` package. This allows you
13 | to create your own custom set of user specific documentation for reference
14 | materials you often refer to, all without having to leave Sublime.
15 |
16 |
17 | # Navigating Help
18 | =================
19 |
20 | This tab contains a HyperHelp |help view| for displaying help text. Along with
21 | regular text, help files can also contain some simple |markup|. The most
22 | important things to keep in mind are:
23 |
24 | * Text within `|` characters are |links|, which take you to other
25 | navigation locations in a help file.
26 | * Text within `*` characters are |anchors|, which provide the destination
27 | that a link jumps to.
28 | * Lines that begin with `#` are |headings|, which are special anchors that
29 | allow you to quickly jump to a section in the current file using the
30 | Sublime Text `symbol list` (see `Goto > Goto Symbol` in the main menu).
31 |
32 | The common navigation keys you're used to using in Sublime allow you to move
33 | around within help files. Additionally, the following additional key bindings
34 | are also available:
35 |
36 | >
37 | Open the |table of contents|. This gives you a hierarchical view of the
38 | help layout for this package.
39 |
40 |
41 | Open the topic index. This allows you to jump immediately to any help
42 | topic in the current package.
43 |
44 | /
45 | Move the cursor to the next or previous |anchor| or |heading| within
46 | the current help file.
47 |
48 | /
49 | Follow a |link|; the help view will switch to the appropriate location
50 | in the target help file. Some links can also open web pages or files in
51 | packages. Hover your mouse over a link to see where it leads.
52 |
53 | /
54 | As in your web browser, HyperHelp keeps a |history| of what help topics
55 | you have been viewing. These keys allow you to navigate forward and
56 | backward through your history.
57 |
58 |
59 | Open a quick panel with your topic history, allowing you to jump
60 | directly to any help topic you have previously viewed.
61 |
62 |
63 | Create a |bookmark| so you can find this topic again easier in the
64 | future. You can use the command palette to jump to a bookmark.
65 |
66 |
67 | Opens the bookmark selector to allow you to quickly jump to an existing
68 | bookmark.
69 |
70 |
71 | # Help View
72 | ===========
73 |
74 | Each Sublime window has it's own `help view` with a |history| independent of
75 | other help views in other windows. This allows you to keep the help most
76 | relevant to the work at hand available.
77 |
78 | A single help view always displays help provided by one package at a time,
79 | although you can freely switch the help package at any time in order to see
80 | more relevant help.
81 |
82 |
83 | # History
84 | =========
85 |
86 | Each |help view| records a history of the topics that it has displayed since it
87 | was created. This works similarly to how history works in your web browser:
88 |
89 | * Opening a new help file adds that file to the end of the history.
90 |
91 | * When moving backwards and forwards through the history, the file and
92 | cursor position is saved before a topic is left and restored to what it
93 | was when you return.
94 |
95 | It is important to note that if you move backwards through history to a
96 | previous topic and then navigate to a new help file, the previous history after
97 | the current topic is replaced with the new topic you visited.
98 |
99 | See the section on |navigating help| for information on how to move through
100 | history in the help view.
101 |
102 |
103 | # _none:Bookmarks
104 | ===========
105 |
106 | HyperHelp allows you to create bookmarks to your most frequently used help
107 | topics, allowing you to quickly find what you're looking for. While in the help
108 | view, the key will create a bookmark at your current location, while the
109 | key will allow you to jump directly to a bookmark.
110 |
111 | More information on the various types of bookmarks is outlined in
112 | |bookmarks.txt|.
113 |
114 |
115 | # Opening Help
116 | ==============
117 |
118 | Opening the initial help view in a window can be accomplished by:
119 |
120 |
121 | * Selecting `HyperHelp: Browse Available Help` in the command palette or
122 | `Help > HyperHelp > Browse Available Help...` from the menu will show you
123 | a list of all packages that currently provide help.
124 |
125 | * Custom key bindings, command palette entries or menu items that use the
126 | appropriate |commands| to open help for a package. These can be created by
127 | you or by a package author.
128 |
129 | * Packages can open context sensitive help to provide more information on
130 | their operation at any point. How this works is up to the package author
131 | and the package in question.
132 |
133 |
134 | # _none:Next Steps
135 | ============
136 |
137 | Now that you know a little bit more about HyperHelp, feel free to explore the
138 | help system a little bit and see what you can do.
139 |
140 | To begin, use the > key to open the |table of contents| for this help and
141 | explore around to get more information on how things work.
142 |
143 | If you're a package author you may want to check out |integration.txt| to see
144 | how you can integrate HyperHelp into your own package (pro tip: it's super
145 | easy).
146 |
147 | You may also want to check out |authoring.txt| to see more information on how
148 | to create help files and the authoring tools that are available.
149 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/help/hyperhelp.json.sublime-ignored:
--------------------------------------------------------------------------------
1 | {
2 | "package": "HyperHelp",
3 | "description": "HyperHelp System Documentation",
4 | "doc_root": "help/",
5 | "default_caption": "Topic {topic} in help source {source}",
6 |
7 | "help_files": {
8 | "index.txt": [
9 | "HyperHelp: About HyperHelp",
10 |
11 | {
12 | "topic": "what is hyperhelp",
13 | "caption": "HyperHelp: What is it?"
14 | },
15 | {
16 | "topic": "how it works",
17 | "caption": "HyperHelp: How it works"
18 | },
19 | {
20 | "topic": "bootstrapping",
21 | "caption": "HyperHelp: Bootstrapping"
22 | },
23 | {
24 | "topic": "help files",
25 | "caption": "HyperHelp: Help Files"
26 | },
27 | {
28 | "topic": "example",
29 | "caption": "Example Anchor"
30 | }
31 | ],
32 |
33 | "help_on_help.txt": [
34 | "How to use HyperHelp",
35 |
36 | {
37 | "topic": "introduction",
38 | "caption": "Introduction to HyperHelp"
39 | },
40 | {
41 | "topic": "navigating help",
42 | "caption": "Navigating Help"
43 | },
44 | {
45 | "topic": "help view",
46 | "caption": "The Help view"
47 | },
48 | {
49 | "topic": "opening help",
50 | "caption": "Opening HyperHelp"
51 | },
52 | {
53 | "topic": "history",
54 | "caption": "Help History"
55 | }
56 | ],
57 |
58 | "syntax.txt": [
59 | "HyperHelp: Help Syntax",
60 |
61 | {
62 | "topic": "file header",
63 | "caption": "Help Header Definition",
64 | "aliases": ["header"]
65 | },
66 | {
67 | "topic": "markup",
68 | "caption": "Markup - Overview"
69 | },
70 | {
71 | "topic": "key bindings",
72 | "caption": "Markup - Key Bindings"
73 | },
74 | {
75 | "topic": "code blocks",
76 | "caption": "Markup - Code Blocks"
77 | },
78 | {
79 | "topic": "anchors",
80 | "caption": "Markup - Anchors",
81 | "aliases": ["anchor"]
82 | },
83 | {
84 | "topic": "headings",
85 | "caption": "Markup - Headings",
86 | "aliases": ["heading"]
87 | },
88 | {
89 | "topic": "links",
90 | "caption": "Markup - Links",
91 | "aliases": ["link"]
92 | },
93 | {
94 | "topic": "separators",
95 | "caption": "Markup - Visual Separators"
96 | },
97 | {
98 | "topic": "comments",
99 | "caption": "Markup - Comments"
100 | }
101 | ],
102 |
103 | "style.txt": [
104 | "HyperHelp: Style Conventions",
105 | ],
106 |
107 | "authoring.txt": [
108 | "HyperHelp: Authoring Help",
109 |
110 | {
111 | "topic": "authoring overview",
112 | "caption": "Authoring Overview"
113 | },
114 | {
115 | "topic": "help index loading",
116 | "caption": "Help Index Loading"
117 | },
118 | {
119 | "topic": "navigating topics",
120 | "caption": "Navigating Topics"
121 | }
122 | ],
123 |
124 | "help_index.txt": [
125 | "Help Index Files",
126 |
127 | {
128 | "topic": "help_index.txt",
129 | "caption": "hyperhelp.json",
130 | "aliases": ["hyperhelp.json"]
131 | },
132 | {
133 | "topic": "package description",
134 | "caption": "Help Index: Package Description"
135 | },
136 | {
137 | "topic": "package",
138 | "caption": "hyperhelp.json: package key"
139 | },
140 | {
141 | "topic": "description",
142 | "caption": "hyperhelp.json: description key"
143 | },
144 | {
145 | "topic": "doc_root",
146 | "caption": "hyperhelp.json: doc_root key"
147 | },
148 | {
149 | "topic": "default_caption",
150 | "caption": "hyperhelp.json: default_caption key"
151 | },
152 | {
153 | "topic": "help_files",
154 | "caption": "hyperhelp.json: help_files key"
155 | },
156 | {
157 | "topic": "help_contents",
158 | "caption": "hyperhelp.json: help_contents key"
159 | },
160 | {
161 | "topic": "children",
162 | "caption": "help_contents: children key"
163 | },
164 | {
165 | "topic": "external resources",
166 | "caption": "hyperhelp.json: External Resources"
167 | },
168 | {
169 | "topic": "externals",
170 | "caption": "hyperhelp.json: externals key"
171 | },
172 | {
173 | "topic": "help topics",
174 | "caption": "hyperhelp.json: Help Topics"
175 | },
176 | {
177 | "topic": "topic",
178 | "caption": "Help Topics: topic key"
179 | },
180 | {
181 | "topic": "caption",
182 | "caption": "Help Topics: caption key"
183 | },
184 | {
185 | "topic": "aliases",
186 | "caption": "Help Topics: aliases key"
187 | },
188 | {
189 | "topic": "table of contents",
190 | "caption": "Table of Contents"
191 | }
192 | ],
193 |
194 | "integration.txt": [
195 | "Integrating HyperHelp",
196 |
197 | {
198 | "topic": "integration.txt",
199 | "caption": "Integrating HyperHelp into your Package"
200 | }
201 | ],
202 |
203 | "settings.txt": [
204 | "HyperHelp Settings",
205 |
206 | {
207 | "topic": "package settings",
208 | "caption": "HyperHelp Package Settings"
209 | },
210 | {
211 | "topic": "dependency settings",
212 | "caption": "HyperHelp Dependency Settings"
213 | },
214 | {
215 | "topic": "hyperhelp_date_format",
216 | "caption": "Setting: hyperhelp_date_format"
217 | },
218 | {
219 | "topic": "show_changelog",
220 | "caption": "Setting: show_changelog"
221 | },
222 | {
223 | "topic": "focus_links_at_top",
224 | "caption": "Setting: focus_links_at_top"
225 | },
226 | {
227 | "topic": "hyperhelp.ignore_disabled",
228 | "caption": "Setting: hyperhelp.ignore_disabled"
229 | }
230 | ],
231 |
232 | "commands.txt": [
233 | "HyperHelp Commands",
234 |
235 | {
236 | "topic": "command overview",
237 | "caption": "Command Overview",
238 | "aliases": ["commands"]
239 | },
240 | {
241 | "topic": "hyperhelp_topic",
242 | "caption": "Command: hyperhelp_topic"
243 | },
244 | {
245 | "topic": "hyperhelp_contents",
246 | "caption": "Command: hyperhelp_contents"
247 | },
248 | {
249 | "topic": "hyperhelp_index",
250 | "caption": "Command: hyperhelp_index"
251 | },
252 | {
253 | "topic": "hyperhelp_navigate",
254 | "caption": "Command: hyperhelp_navigate"
255 | },
256 | {
257 | "topic": "hyperhelp_current_help",
258 | "caption": "Command: hyperhelp_current_help"
259 | },
260 | {
261 | "topic": "hyperhelp_history",
262 | "caption": "Command: hyperhelp_history"
263 | },
264 | {
265 | "topic": "hyperhelp_create_bookmark",
266 | "caption": "Command: hyperhelp_create_bookmark"
267 | },
268 | {
269 | "topic": "hyperhelp_prompt_create_bookmark",
270 | "caption": "Command: hyperhelp_prompt_create_bookmark"
271 | },
272 | {
273 | "topic": "hyperhelp_open_bookmark",
274 | "caption": "Command: hyperhelp_open_bookmark"
275 | }
276 | ],
277 |
278 | "key_contexts.txt": [
279 | "HyperHelp Key Contexts",
280 |
281 | {
282 | "topic": "key_contexts.txt",
283 | "caption": "HyperHelp Key Contexts",
284 | "aliases": ["key contexts"]
285 | },
286 | {
287 | "topic": "context overview",
288 | "caption": "Context: context overview"
289 | },
290 | {
291 | "topic": "hyperhelp.is_help_view",
292 | "caption": "Context: hyperhelp.is_help_view"
293 | },
294 | {
295 | "topic": "hyperhelp.is_help_visible",
296 | "caption": "Context: hyperhelp.is_help_visible"
297 | },
298 | {
299 | "topic": "hyperhelp.is_help",
300 | "caption": "Context: hyperhelp.is_help"
301 | },
302 | {
303 | "topic": "hyperhelp.is_help_source",
304 | "caption": "Context: hyperhelp.is_help_source"
305 | },
306 | {
307 | "topic": "hyperhelp.is_help_index",
308 | "caption": "Context: hyperhelp.is_help_index"
309 | },
310 | {
311 | "topic": "hyperhelp.is_help_package",
312 | "caption": "Context: hyperhelp.is_help_package"
313 | },
314 | {
315 | "topic": "hyperhelp.is_help_file",
316 | "caption": "Context: hyperhelp.is_help_file"
317 | }
318 | ],
319 |
320 | "api.txt": [
321 | "HyperHelp API",
322 |
323 | {
324 | "topic": "api.txt",
325 | "caption": "HyperHelp API",
326 | "aliases": ["api"]
327 | },
328 | {
329 | "topic": "api overview",
330 | "caption": "API Overview"
331 | }
332 | ],
333 |
334 | "bookmarks.txt": [
335 | "HyperHelp Bookmarks",
336 |
337 | {
338 | "topic": "bookmarks",
339 | "caption": "About Bookmarks",
340 | "aliases": ["bookmark"]
341 | },
342 | {
343 | "topic": "creating bookmarks",
344 | "caption": "Bookmarks: Creation"
345 | },
346 | {
347 | "topic": "file bookmark",
348 | "caption": "Bookmarks: File Bookmark"
349 | },
350 | {
351 | "topic": "view bookmark",
352 | "caption": "Bookmarks: View Bookmark"
353 | },
354 | {
355 | "topic": "topic bookmark",
356 | "caption": "Bookmarks: Topic Bookmark"
357 | }
358 | ],
359 |
360 | "example.txt": [
361 | "Help Examples",
362 |
363 | {
364 | "topic": "example hyperhelp.json",
365 | "caption": "Example hyperhelp.json Index File"
366 | },
367 | {
368 | "topic": "example index.txt",
369 | "caption": "Example index.txt Help File"
370 | }
371 | ],
372 |
373 | "changelog.txt": [
374 | "HyperHelp ChangeLog",
375 |
376 | {
377 | "topic": "latest_update",
378 | "caption": "ChangeLog: Recent Changes"
379 | },
380 | ],
381 | },
382 |
383 | "externals": {
384 | "https://github.com/STealthy-and-haSTy/HyperHelpAuthor": [
385 | "HyperHelpAuthor: Help Authoring Package",
386 |
387 | { "topic": "HyperHelpAuthor"}
388 | ],
389 |
390 | "https://github.com/STealthy-and-haSTy/SnAPI": [
391 | "SnAPI: Sublime Text Documentation",
392 |
393 | { "topic": "SnAPI" }
394 | ],
395 |
396 | "https://github.com/STealthy-and-haSTy/hyperhelpcore": [
397 | "hyperhelpcore: The HyperHelp core Dependency",
398 |
399 | { "topic": "hyperhelpcore" }
400 | ],
401 |
402 |
403 | "https://packagecontrol.io/docs/dependencies": [
404 | "Package Control Dependency Documentation",
405 |
406 | { "topic": "Package Control Dependency Documentation" }
407 | ],
408 |
409 | "https://odatnurd.net/overrideaudit/": [
410 | "OverrideAudit Home Page",
411 |
412 | { "topic": "OverrideAudit" }
413 | ],
414 |
415 | "https://packagecontrol.io/packages/PackageDev": [
416 | "PackageDev: Sublime Text utility package",
417 |
418 | { "topic": "PackageDev"}
419 | ],
420 |
421 | "https://json.org/": [
422 | "Introducing JSON",
423 |
424 | { "topic": "json" }
425 | ],
426 |
427 | "https://docs.python.org/3.3/": [
428 | "Python 3.3.7 documentation",
429 |
430 | { "topic": "python 3.3 docs" }
431 | ],
432 |
433 | "https://docs.python.org/3.3/library/datetime.html#strftime-and-strptime-behavior": [
434 | "strftime() and strptime() Behavior",
435 |
436 | { "topic": "strftime() and strptime() Behavior" }
437 | ],
438 |
439 | "Packages/Default/exec.py": [
440 | "The default exec command",
441 |
442 | { "topic": "exec.py" }
443 | ],
444 |
445 | "Packages/User/Preferences.sublime-settings": [
446 | "User specific Sublime Settings",
447 |
448 | {
449 | "topic": "Preferences.sublime-settings",
450 | "aliases": ["your user preferences"]
451 | }
452 | ]
453 | },
454 |
455 | "help_contents": [
456 | {
457 | "caption": "Change History",
458 | "topic": "changelog.txt"
459 | },
460 | "help_on_help.txt",
461 | "what is hyperhelp",
462 | "settings.txt",
463 | {
464 | "topic": "syntax.txt",
465 | "children": [
466 | "syntax.txt",
467 | "markup",
468 | "anchors",
469 | "headings",
470 | "links",
471 | "code blocks",
472 | "key bindings",
473 | "comments",
474 | "separators"
475 | ]
476 | },
477 | "commands.txt",
478 | "style.txt",
479 | "authoring.txt",
480 | "integration.txt",
481 | ]
482 | }
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/help/index.txt:
--------------------------------------------------------------------------------
1 | %hyperhelp title="HyperHelp: About HyperHelp" date="2019-03-25"
2 |
3 |
4 | # What is HyperHelp
5 | ===================
6 |
7 | HyperHelp is a hypertext help system for Sublime Text 3 in a vein similar to
8 | the help system in other text editors such as `vim` and `emacs`. The goal is to
9 | bridge the gap between providing just a simple text file (e.g. a `README` file)
10 | and a full HTML based documentation site.
11 |
12 | HyperHelp employs simple plain text files (with some |markup|) but also
13 | provides the power of web based documentation by allowing you to easily find
14 | and navigate from help file to help file and topic to topic, including the
15 | ability to navigate through the history of your help viewing and bookmarking
16 | often used topics.
17 |
18 | If you're new to HyperHelp, more immediate help on how to use it is available
19 | in |heLp_on_help.txt|. To view it, follow the link by either double clicking it
20 | or putting the text cursor on the underlined text and pressing enter.
21 |
22 |
23 | # How it works
24 | ==============
25 |
26 | HyperHelp is special in that it consists of two parts; a `dependency` library
27 | that Sublime Text packages can depend on and which provides the core API of the
28 | help system itself, and a `package` that provides the commands and extensions
29 | that use the API to allow you to navigate help.
30 |
31 | Due to this hybrid nature, you cannot directly install HyperHelp. Instead, it
32 | will automatically be installed when you use a package that wants to provide
33 | help using HyperHelp.
34 |
35 | When HyperHelp is first installed, it |:bootstrapping:bootstraps| itself in order to finalize
36 | the setup process. This bootstrap process also happens whenever HyperHelp is
37 | upgraded, in order to finalize the upgrade.
38 |
39 | These operations are transparent to you; you'll see a popup whenever they occur
40 | to let you know what's going on, but otherwise you can just get on with
41 | business as usual.
42 |
43 |
44 | # Help Files
45 | ============
46 |
47 | Your interaction with HyperHelp takes place in the context of Help Files. These
48 | files are plain text files with minimal |markup| and are grouped together
49 | according to the `package` they provide help for.
50 |
51 | The available help markup is somewhat similar to `Markdown`, but is designed to
52 | be more easily human readable since there is no extra display steps other than
53 | syntax highlighting.
54 |
55 | `NOTE:` Although Sublime Text does allow for display of HTML in documents
56 | by using |SublimeAPI:phantom:phantoms|, HyperHelp does not use them for help content
57 | because you cannot copy the content of a phantom for use elsewhere.
58 |
59 | The two main aspects of help files are *example:anchors* and |:example:links|. An `anchor` is a
60 | navigation point in a document that is considered to be a point of interest in
61 | that document (a section title, information on a topic, and so on), while a
62 | `link` allows you to jump directly to any anchor. The first sentence of this
63 | paragraph contains an |anchor| followed by a |link| that links to it.
64 |
65 | In order to be as easy to use as possible, HyperHelp is almost entirely
66 | transparent to both package authors that want to add help to their packages as
67 | well as to the end user of the help system.
68 |
69 | This means that as a package developer, you only need to follow the simple
70 | steps in |integration.txt| to ensure that HyperHelp will be available to your
71 | package users, and then focus on writing your help.
72 |
73 | Once you've followed the integration steps, you can use Sublime itself to
74 | create your help content, or use the |HyperHelpAuthor| package to help you
75 | create the appropriate files. More information on creating help files can be
76 | found in |authoring.txt|. A simple example of the required files is also
77 | available in |example.txt|.
78 |
79 | HyperHelp is designed to be used not only as a system for displaying generic
80 | help but also context specific help. To that end you can optionally also use
81 | the |api|, |commands| and |key contexts| provided to customize the help
82 | experience your users have with your package and HyperHelp.
83 |
84 |
85 | # Bootstrapping
86 | ===============
87 |
88 | HyperHelp is different than standard packages that you might have used with
89 | Sublime Text in that it consists of two parts; a `dependency` library that
90 | provides the core of the help API, and a `package` that exposes the API and
91 | acts as you would expect a package to act.
92 |
93 | The HyperHelp package itself is shipped inside of the dependency, and the act
94 | of copying it out and deploying it as a standard package is known as
95 | `bootstrapping` the package.
96 |
97 | The bootstrap is seamless and happens automatically when required:
98 |
99 | * When the first package that uses HyperHelp is installed, the dependency
100 | will be installed and will bootstrap the HyperHelp package
101 |
102 | * If the dependency is updated, a new version of the HyperHelp package will
103 | be bootstrapped in order to keep things up to date
104 |
105 | * If the HyperHelp package is missing, a new copy will be created to put the
106 | system back into working order
107 |
108 | Whenever a bootstrap occurs, a dialog box will pop up to tell you that it
109 | happened. In some cases (such as when the dependency has been updated), you may
110 | be required to restart Sublime Text in order for the update to finish; the
111 | dialog will tell you when this is the case.
112 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/help/integration.txt:
--------------------------------------------------------------------------------
1 | %hyperhelp title="Integrating HyperHelp" date="2019-03-25"
2 |
3 |
4 | # _none:Integrating HyperHelp into your Package
5 | ==========================================
6 |
7 | One of the core design goals of HyperHelp is to be as easy as possible to
8 | integrate with any package in order to promote a simple, easily accessible and
9 | useful help system that provides consistency for the user.
10 |
11 | Follow this simple set of steps in order to add HyperHelp support to your
12 | package:
13 |
14 |
15 | ## _none:Step 1: Add a dependency on `hyperhelpcore`
16 | ----------------------------------------------
17 |
18 | As HyperHelp is shipped as a dependency, you need to modify your package to
19 | indicate to Package Control that it depends on `hyperhelpcore`; doing so
20 | will cause Package Control to automatically install HyperHelp for you as
21 | needed.
22 |
23 | See the |Package Control Dependency Documentation| for full details, but
24 | to get started, add a file named `dependencies.json` to your package with
25 | the following contents:
26 |
27 | ```json
28 | {
29 | "*": {
30 | "*": [
31 | "hyperhelpcore"
32 | ]
33 | }
34 | }
35 | ```
36 |
37 | Once you've done this, select `Package Control: Satisfy Dependencies` from
38 | the command palette to tell Package Control to install the dependency for
39 | you.
40 |
41 |
42 | ## _none:Step 2: Initialize the help system in `plugin_loaded()`
43 | ----------------------------------------------------------
44 |
45 | Since HyperHelp is a dependency and needs to |:bootstrapping:bootstrap| the user facing
46 | package if it hasn't already, all packages that want active HyperHelp
47 | support need to tell it to perform that step if needed.
48 |
49 | To do this, add the following code to one of the plugins in your package.
50 | If that plugin already has a `plugin_loaded()` endpoint, don't create a
51 | second one; add the line of code here to yours:
52 |
53 | ```python
54 | import hyperhelpcore
55 |
56 | def plugin_loaded():
57 | hyperhelpcore.initialize()
58 |
59 | ```
60 |
61 | Once you save the plugin, `hyperhelpcore.initialize()` will be invoked,
62 | which will cause the first boostrap to occur, finalizing the install. Going
63 | forward, on every startup `hyperhelpcore` will check to verify that the
64 | bootstrapped package exists and is up to date.
65 |
66 |
67 | ## _none:Step 3: Author your Help
68 | ---------------------------
69 |
70 | You've now told Package Control that your package depends on HyperHelp so
71 | that it will be installed, and you've told HyperHelp at load time that it
72 | should check and verify that everything is running, so all that's left is
73 | to write your help.
74 |
75 | This is likely the hardest part of the entire operation. There is more
76 | information on creating help in |authoring.txt|. You may also find
77 | |syntax.txt| useful as a guide to the help file syntax.
78 |
79 |
80 | ## _none:Step 4: Implement context sensitive help (optional)
81 | ------------------------------------------------------
82 |
83 | Although not strictly required, the power of HyperHelp allows you to create
84 | customized, context sensitive help for your package or help system by using
85 | the built in |commands|, |key contexts| and |api|.
86 |
87 | These allow you to include things like a custom key bindings or commands
88 | that jump directly from something in your package directly to associated
89 | help, and so on.
90 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/help/key_contexts.txt:
--------------------------------------------------------------------------------
1 | %hyperhelp title="HyperHelp Key Contexts" date="2019-03-23"
2 |
3 |
4 | # Context Overview
5 | ==================
6 |
7 | HyperHelp provides several |commands|, key contexts and an |api| that allow you
8 | to customize the help experience for yourself or for users of your package by
9 | creating your own custom key bindings, menu entries or plugins.
10 |
11 | The key contexts listed here can be used in key bindings in order to ensure
12 | that your bindings only take effect in the appropriate circumstances.
13 |
14 |
15 | ## hyperhelp.is_help_view
16 | -------------------------
17 |
18 | key: `"hyperhelp.is_help_view"`
19 | operator: `"equal"`, `"not_equal"`
20 | operand: `true`, `false`
21 |
22 | This context yields `true` when the currently focused view in the current
23 | window is a |help view|.
24 |
25 |
26 | ## hyperhelp.is_help_visible
27 | -------------------------
28 |
29 | key: `"hyperhelp.is_help_visible"`
30 | operator: `"equal"`, `"not_equal"`
31 | operand: `true`, `false`
32 |
33 | This context yields `true` when the current window has a |help view| already
34 | created within it. This is not an indication that the help view is currently
35 | focused, only that it exists.
36 |
37 |
38 | ## hyperhelp.is_help
39 | -------------------------
40 |
41 | key: `"hyperhelp.is_help"`
42 | operator: `"equal"`, `"not_equal"`
43 | operand: `true`, `false`
44 |
45 | This context yields `true` when the currently focused view in the current
46 | window contains a hyperhelp source file; that is, a file whose syntax indicates
47 | that it is a HyperHelp help file.
48 |
49 | This is true for any file using the appropriate syntax, which includes not only
50 | the contents of the |help view| but also a help file that you might be
51 | |:authoring.txt:authoring|.
52 |
53 |
54 |
55 | ## hyperhelp.is_help_source
56 | -------------------------
57 |
58 | key: `"hyperhelp.is_help_source"`
59 | operator: `"equal"`, `"not_equal"`
60 | operand: `true`, `false`
61 |
62 | This context extends |hyperhelp.is_help| by only yielding `true` when the
63 | current help file is a help file that is not being authored; that is, it is
64 | marked as read-only.
65 |
66 |
67 | ## hyperhelp.is_help_index
68 | -------------------------
69 |
70 | key: `"hyperhelp.is_help_index"`
71 | operator: `"equal"`, `"not_equal"`
72 | operand: `true`, `false`
73 |
74 | This context yields `true` when the currently focused view in the current
75 | window contains a hyperhelp index file; that is, a file whose syntax indicates
76 | that it is a HyperHelp index file.
77 |
78 |
79 | ## hyperhelp.is_help_package
80 | -------------------------
81 |
82 | key: `"hyperhelp.is_help_package"`
83 | operator: `"equal"`, `"not_equal"`
84 | operand: a string that is a package name
85 |
86 | This context yields `true` when the current window contains a |help view| and
87 | the currently displayed help file is displaying a help file for the given
88 | package.
89 |
90 |
91 | ## hyperhelp.is_help_file
92 | -------------------------
93 |
94 | key: `"hyperhelp.is_help_file"`
95 | operator: `"equal"`, `"not_equal"`
96 | operand: a string that is a package name
97 |
98 | This context yields `true` when the current window contains a |help view| and
99 | the currently displayed help file has the same name as the help file given.
100 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/help/settings.txt:
--------------------------------------------------------------------------------
1 | %hyperhelp title="HyperHelp Settings" date="2020-04-06"
2 |
3 |
4 | # _none:Settings Overview
5 | ===================
6 |
7 | Like most packages, HyperHelp allows you to customize its behaviour by
8 | providing various settings for you to configure as you see fit. However, unlike
9 | most packages, HyperHelp consists of both a dependency that powers the help
10 | system and a regular package that allows you to interact with it.
11 |
12 | For this reason, some settings are specific to the HyperHelp package and work
13 | like normal package settings, while others are specific to the dependency and
14 | go in the global |Preferences.sublime-settings| preferences file instead.
15 |
16 |
17 | ## Package Settings
18 | -------------------
19 |
20 | The settings here go in the HyperHelp specific settings file, which you can get
21 | to by selecting `Preferences > Package Settings > HyperHelp > Settings` from
22 | the main menu.
23 |
24 | *hyperhelp_date_format*
25 |
26 | This setting controls the format of the last modification date that
27 | appears in the |header| line of all help files. Changes to this setting
28 | will be applied when the next help file is loaded.
29 |
30 | The default value for this is setting is `%x`, which sets a date format
31 | that's appropriate for the area of the world in which you live.
32 |
33 | You can use any of the format specifiers given in the |Python 3.3 docs|
34 | on the |strftime() and strptime() behavior| page.
35 |
36 | Note however that no time stamps are stored for file times, only dates.
37 | As such you should avoid any fields that tell you the time of the day.
38 |
39 | *show_changelog*
40 |
41 | When this setting is enabled (which is the default), when HyperHelp is
42 | first installed it will display the |help_on_help.txt| file to help you
43 | learn how to use it.
44 |
45 | Similarly, whenever the package is upgraded the |:latest_update:latest entry| in the
46 | |changelog.txt| file will be displayed to keep you informed on the most
47 | recent changes and bug fixes.
48 |
49 | *focus_links_at_top*
50 |
51 | When this setting is enabled (which is the default), HyperHelp will
52 | focus the anchor of the link at the top of the help view. When
53 | disabled, the link achor will be centered in the help view instead.
54 |
55 | This setting does not affect the focus of anchors during anchor
56 | navigation through the file.
57 |
58 |
59 | ## Dependency Settings
60 | ----------------------
61 |
62 | The settings here are referenced by the dependency portion of HyperHelp and go
63 | in the |Preferences.sublime-settings| file because they need to be available
64 | even if the HyperHelp package is ignored or unavailable.
65 |
66 | If you use the |PackageDev| package, it will syntax highlight these settings
67 | differently, and will also provide auto-complete and hover popups for them as
68 | well.
69 |
70 | *hyperhelp.ignore_disabled*
71 |
72 | Normally, the hyperhelp core dependency performs a check at startup to
73 | ensure that the HyperHelp package itself is not in the list of ignored
74 | packages.
75 |
76 | This is to ensure that problems caused by partial |:bootstrapping:bootstraps| don't go
77 | unnoticed, which can cause confusing issues.
78 |
79 | Should you actually want to have HyperHelp in the list of ignored
80 | packages, this setting should be added to your user preferences to tell
81 | the core that you intentionally ignored HyperHelp.
82 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/help/style.txt:
--------------------------------------------------------------------------------
1 | %hyperhelp title="HyperHelp: Style Conventions" date="2019-03-25"
2 |
3 |
4 | # _none:Style Conventions
5 | ===================
6 |
7 | In order to remain as consistent as possible for all users of help, HyperHelp
8 | includes customized syntax specific settings for the |help view|.
9 |
10 | * `word_wrap` is disabled, so all help should optimally be presentable in
11 | no more than 80 characters of text. This matches the width of the
12 | generated |file header| in the displayed help.
13 |
14 | * `translate_tabs_to_spaces` is enabled for help files to ensure identical
15 | formatting for both the help author and the person viewing the help.
16 |
17 |
18 | # _none:View Conventions
19 | ==================
20 |
21 | In addition to the style rules outlined above, several settings are included in
22 | the syntax specific settings of the |help view| in order to provide a cleaner
23 | appearance.
24 |
25 | * `rulers` are disabled
26 |
27 | * `fade_fold_buttons` and `draw_indent_guides` are enabled and disabled
28 | respectively, since help text tends to be more free form and less code
29 | based, where indentation levels are less ordered.
30 |
31 | * `match_selection` is turned off to avoid visual noise when text is
32 | selected, such as when navigating between |anchors|
33 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/help/syntax.txt:
--------------------------------------------------------------------------------
1 | %hyperhelp title="HyperHelp: Help Syntax" date="2019-03-25"
2 |
3 |
4 | # _none:Help Syntax Overview
5 | ======================
6 |
7 | Help files in HyperHelp are plain text files with an extension of `.txt` that
8 | support a minimal |markup| language to provide emphasis and navigation hints to
9 | the help system. Each help file in a help package must be referenced in the
10 | |hyperhelp.json| help index for the package so that HyperHelp knows that it
11 | exists.
12 |
13 | `NOTE:` Every help package should contain a file named `index.txt`, which
14 | is used as the default entry point for help in the package similar
15 | to how `index.html` is used for folders in web pages.
16 |
17 |
18 | # File Header
19 | =============
20 |
21 | Every HyperHelp help file should start with a header structured as follows:
22 |
23 | ```
24 | %hyperhelp title="Help File Title" date="YYYY-MM-DD"
25 | ```
26 |
27 |
28 | When the help file is loaded into the |help view|, the header will be parsed
29 | and converted into a standard header line in the buffer. The title of the file
30 | is always centered within the 80 column width of the help view, and the date is
31 | displayed in a user-selectable format via the |hyperhelp_date_format| setting.
32 |
33 | The file header is not mandatory, but it is highly recommended that your help
34 | files contain one. This helps to ensure that all help displayed to the user is
35 | in a consistent format and ensures that every help file can be easily opened by
36 | name (since the expanded header contains the file name as an |anchor|).
37 |
38 |
39 | # Markup
40 | ========
41 |
42 | Although HyperHelp is primarily plain text, there is a small markup language
43 | provided to add navigation information and visual emphasis where needed.
44 |
45 | Bu design, all markup is simple, contextual and non-ambiguous due to how
46 | Sublime Text syntax highlighting is performed.
47 |
48 |
49 | ## Anchors
50 | ----------
51 |
52 | Normal: `*topic:anchor text*`
53 | `*:anchor text*`
54 | `*anchor text*`
55 |
56 | Hidden: `*|topic:anchor text|*`
57 | `*|:anchor text|*`
58 | `*|anchor text|*`
59 |
60 | `NOTE:` All anchors must have a unique `topic` (|headings| and anchors
61 | share the same topic name space). The special topic `_none` can
62 | be used to indicate an anchor can be navigated to by keyboard
63 | but not by a link (for example a section header).
64 |
65 |
66 | Anchors represent points of interest in help documents; they declare the
67 | point where a |topic| navigates to. Navigation to an anchor can occur as
68 | the result of following a link, as well as via keyboard navigation in a
69 | file; by default this is the and keys.
70 |
71 | The body of the anchor itself is of the form `topic:text`, which indicates
72 | that this anchor represents a topic named `topic`, but presents in the file
73 | as `text` instead.
74 |
75 | Since it is a common idiom for an anchor to use a topic and text that are
76 | identical, `*topic:topic*`, `*:topic*` and `*topic*` are treated as being
77 | the same; an anchor whose topic is identical to it's text. The second form
78 | is required when the topic text contains a literal `:` character, since in
79 | that case the result would be ambiguous.
80 |
81 | There are two styles of anchor, `Normal` and `Hidden`; the only functional
82 | difference between the two is that `normal` anchors are represented in the
83 | resulting text file wrapped in `*asterisks`, while a hidden anchor is not
84 | visibly distinct from the surrounding text in any way.
85 |
86 |
87 | ## Headings
88 | -----------
89 |
90 | `# topic:text`
91 | `## topic:text`
92 | `### topic:text`
93 |
94 | `NOTE:` All anchors must have a unique `topic` (headings and |anchors|
95 | share the same topic name space). The special topic `_none` can
96 | be used to indicate an anchor can be navigated to by keyboard
97 | but not by a link (for example a section header).
98 |
99 |
100 | A heading is a special case of a normal |anchor|, which is prefixed by one
101 | or more `#` characters to indicate what level of heading that it is. As
102 | they are treated as anchors, topics can link to them.
103 |
104 | Headers are visually distinct from normal anchors due to their `#` prefix.
105 | Their purpose is to allow for easier navigation within the sections of a
106 | file by using `Goto > Goto Symbol`.
107 |
108 | In the symbol list, headers are displayed with an indentation level that
109 | corresponds to the number of `#` prefix characters they have, up to an
110 | indentation level of three.
111 |
112 |
113 | ## Links
114 | -------
115 |
116 | `|package:topic:text|`
117 | `|:topic:text|`
118 | `|package::text|`
119 | `|::text|`
120 | `|text|`
121 |
122 | `NOTE:` The target of a link is resolved at the time the help file is
123 | loaded into the |help view| and is visible by hovering your
124 | mouse over a link. If the target of a link can not be found,
125 | the link will be visually styled with a different colored
126 | underline to indicate that it is broken.
127 |
128 |
129 | Links are the main method by which a user can interactively jump to another
130 | location in the current or some other help file. You can follow a link by
131 | doing a on the link, or placing the cursor on the link
132 | text and pressing .
133 |
134 | The general form of a link is `package:topic:text`, which indicates that
135 | the link targets the given |topic| in the given help package, and will
136 | display using the provided text.
137 |
138 | The `package` portion is optional and only required for links that target a
139 | topic in a different package; when it is not specified, the default is the
140 | current package. This is demonstrated in the second, fourth and fifth
141 | examples above.
142 |
143 | As with |anchors|, it is a common idiom to link to a topic by using the
144 | topic as the text of the link. In such a case, the topic is also optional
145 | and defaults to the link text, as in the last three examples above.
146 |
147 | In order to avoid ambiguity, if the link text contains a literal `:`
148 | character, all sections must be provided (though you can allow them to
149 | default).
150 |
151 |
152 | ## Code Blocks
153 | -------------
154 |
155 | `Inline Code Block`
156 |
157 | ```
158 | Multi Line Code Block
159 | ```
160 |
161 |
162 | HyperHelp supports both inline code blocks and multi line code blocks in a
163 | manner similar to that used in Markdown. Unlike in standard markdown, it is
164 | not possible to include or quote a back tick inside of an inline code
165 | block.
166 |
167 | Multi line code blocks allow the ability to specify the syntax highlighting
168 | to use. Any value will be accepted, but syntax highlighting will only be
169 | performed for `python`, `py`, `xml`, `plist` and `json`, since these are
170 | the core file formats used by Sublime internally.
171 |
172 |
173 | ## Key Bindings
174 | --------------
175 |
176 | ``
177 | ``
178 | `>`
179 |
180 |
181 | HyperHelp include a simple key binding markup by wrapping text in pairs of
182 | less than and greater than signs. Although intended primarily for use as a
183 | key binding (as the name suggets), there is no internal functionality that
184 | relies on this fact, so you are free to use them for any emphasis that you
185 | want.
186 |
187 | <****>
188 |
189 | ## Comments
190 | -----------
191 |
192 | `<** Comment Text **>`
193 |
194 | `NOTE:` Due to a potential ambiguity, it is not possible to denote
195 | a key binding of four consecutive asterisk characters
196 | without including whitespace of some form; such a binding
197 | will be recognized as a comment instead.
198 |
199 |
200 | A simple comment syntax is allowed in HyperHelp by wrapping text in
201 | `<**` and `**>` sequences.
202 |
203 | When the help file is rendered in the |help view|, the comment is
204 | completely redacted from the contents of the file so that it doesn't appear
205 | to the user at all.
206 |
207 | When the `**>` is followed by the end of the line (with no intervening
208 | characters or whitespace), the end of line character will also be removed
209 | when the comment is redacted.
210 |
211 | This allows you to include comments in locations without adding extra
212 | blank lines to the output.
213 |
214 |
215 | ## Separators
216 | ------------
217 |
218 | `----`
219 | `====`
220 | `+----|----+`
221 | `|`
222 |
223 |
224 | Separators allow for drawing simple horizontal and vertical lines, allowing
225 | you to emphasize text by underlining it (as is done in this help system) as
226 | well as to draw tables:
227 |
228 |
229 | +------------|----------+
230 | | Sample Box | Column 2 |
231 | +============+==========+
232 |
233 |
234 | Horizontal separators consist of four or more consecutive `=` or `-`
235 | characters. Additionally the sequence can begin with an `+` character and
236 | end with a `+` or `|` character to aid in line drawing.
237 |
238 | In addition, any `|` characters which are not a part of a |link| are
239 | considered to be vertical separators and are treated as such.
240 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/internalcmd.py:
--------------------------------------------------------------------------------
1 | import sublime
2 | import sublime_plugin
3 |
4 | import time
5 |
6 | from hyperhelpcore.core import parse_help_header, parse_anchor_body, parse_link_body
7 | from hyperhelpcore.core import help_index_list, lookup_help_topic
8 | from hyperhelpcore.core import is_topic_file, is_topic_file_valid
9 | from hyperhelpcore.help import _get_link_topic
10 | from hyperhelpcore.common import hh_setting
11 | from hyperhelpcore.common import current_help_package, current_help_file
12 |
13 |
14 | ###----------------------------------------------------------------------------
15 |
16 |
17 | def _can_post_process(view):
18 | """
19 | Determine if the provided view is eligible for a post processing command to
20 | execute within it or not.
21 | """
22 | return (view.match_selector(0, "text.hyperhelp.help") and
23 | view.settings().get("_hh_post_processing", False))
24 |
25 |
26 | ###----------------------------------------------------------------------------
27 |
28 |
29 | class HyperhelpInternalProcessHeaderCommand(sublime_plugin.TextCommand):
30 | """
31 | Process the header in a newly loaded help file by finding and replacing the
32 | source level meta header with the fully expanded user-facing header.
33 |
34 | Nothing happens if the current file does not appear to have an appropriate
35 | meta-header line.
36 | """
37 | def run(self, edit):
38 | help_file = current_help_file(self.view)
39 | first_line = self.view.substr(self.view.full_line(0))
40 |
41 | header = parse_help_header(help_file, first_line)
42 | if header is None:
43 | return
44 |
45 | _hdr_width = 80
46 | _time_fmt = hh_setting("hyperhelp_date_format")
47 |
48 | file_target = "*%s*" % help_file
49 | title = header.title
50 | date_str = "Not Available"
51 |
52 | if header.date != 0:
53 | date_str = time.strftime(_time_fmt, time.localtime(header.date))
54 |
55 | # Take into account two extra spaces on either side of the title
56 | max_title_len = _hdr_width - len(file_target) - len(date_str) - 4
57 | if len(title) > max_title_len:
58 | title = title[:max_title_len-1] + '\u2026'
59 |
60 | header_line = "%s %s %s\n%s\n" % (
61 | file_target,
62 | "%s" % title.center(max_title_len, " "),
63 | date_str,
64 | ("=" * _hdr_width)
65 | )
66 |
67 | self.view.replace(edit, self.view.full_line(0), header_line)
68 |
69 | def is_enabled(self):
70 | return _can_post_process(self.view)
71 |
72 |
73 | class HyperhelpInternalProcessCommentsCommand(sublime_plugin.TextCommand):
74 | """
75 | Remove all hyperhelp comments from a newly loaded help file.
76 |
77 | All text scoped as a comment (including newlines) will be redacted from the
78 | file.
79 | """
80 | def run(self, edit):
81 | for region in reversed(self.view.find_by_selector("comment.block.help")):
82 | self.view.erase(edit, region)
83 |
84 | def is_enabled(self):
85 | return _can_post_process(self.view)
86 |
87 |
88 | class HyperhelpInternalProcessAnchorsCommand(sublime_plugin.TextCommand):
89 | """
90 | Process all anchors in a newly loaded help file. This does the work of
91 | rewriting anchors so that only their anchor text appears as well as
92 | removing the markup that makes hidden anchors hidden.
93 |
94 | This results in regions and settings being applied to the view that allow
95 | the help core to navigate within the file.
96 | """
97 | def run(self, edit):
98 | v = self.view
99 | v.add_regions("_hh_anchors", v.find_by_selector("meta.anchor"), "",
100 | flags=sublime.HIDDEN | sublime.PERSISTENT)
101 |
102 | for pos in reversed(v.find_by_selector("punctuation.anchor.hidden")):
103 | v.erase(edit, pos)
104 |
105 | hh_nav = {}
106 | regions = v.get_regions("_hh_anchors")
107 | for idx, region in enumerate(reversed(regions)):
108 | topic, text = parse_anchor_body(v.substr(region))
109 | v.replace(edit, region, text)
110 | hh_nav[topic] = len(regions) - idx - 1
111 |
112 | v.settings().set("_hh_nav", hh_nav)
113 |
114 | def is_enabled(self):
115 | return _can_post_process(self.view)
116 |
117 |
118 | class HyperhelpInternalProcessLinksCommand(sublime_plugin.TextCommand):
119 | """
120 | Process all links in a newly loaded help file. This does the work of
121 | rewriting links so that only their link text appears, while keeping track
122 | of the topic ID and package designations of each link.
123 |
124 | This results in regions and settings being applied to the view that allow
125 | the help core to navigate within the file.
126 | """
127 | def run(self, edit):
128 | v = self.view
129 | regions = v.find_by_selector("meta.link")
130 | default_pkg = current_help_package(self.view)
131 |
132 | v.add_regions("_hh_links", regions, "",
133 | flags=sublime.HIDDEN | sublime.PERSISTENT)
134 |
135 |
136 | hh_links = [None] * len(regions)
137 | for idx,region in enumerate(reversed(regions)):
138 | base_text = v.substr(region)
139 | pkg_name, topic, text = parse_link_body(base_text)
140 | pkg_name = pkg_name or default_pkg
141 |
142 | if text is None:
143 | topic = "_broken"
144 | text = base_text
145 |
146 | v.replace(edit, region, text)
147 | hh_links[len(regions) - idx - 1] = {
148 | "pkg": pkg_name,
149 | "topic": topic
150 | }
151 |
152 | v.settings().set("_hh_links", hh_links)
153 |
154 | v.run_command("hyperhelp_internal_flag_links")
155 |
156 | def is_enabled(self):
157 | return _can_post_process(self.view)
158 |
159 |
160 | class HyperhelpInternalFlagLinksCommand(sublime_plugin.TextCommand):
161 | """
162 | Given a help file which has had its links post processed already via
163 | hyperhelp_internal_process_links, this checks each link in the file and
164 | classifies them as either active or broken, depending on whether or not
165 | they point to a valid destination.
166 |
167 | This is a non-destructive command and may be executed any time the
168 | underlying help indexes may have changed, such as at Sublime startup.
169 | """
170 | def run(self, edit):
171 | v = self.view
172 | active = []
173 | broken = []
174 |
175 | regions = v.get_regions("_hh_links")
176 | for idx, region in enumerate(regions):
177 | link_dat = _get_link_topic(v, idx)
178 |
179 | pkg_info = help_index_list().get(link_dat["pkg"], None)
180 | topic = lookup_help_topic(pkg_info, link_dat["topic"])
181 |
182 | if self.link_is_active(pkg_info, topic):
183 | active.append(region)
184 | else:
185 | broken.append(region)
186 |
187 | v.add_regions("_hh_links_active", active, "storage",
188 | flags=sublime.DRAW_SOLID_UNDERLINE | sublime.PERSISTENT |
189 | sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE)
190 |
191 | v.add_regions("_hh_links_broken", broken, "comment",
192 | flags=sublime.DRAW_STIPPLED_UNDERLINE | sublime.PERSISTENT |
193 | sublime.DRAW_NO_FILL | sublime.DRAW_NO_OUTLINE)
194 |
195 | def link_is_active(self, pkg_info, topic):
196 | if topic is None:
197 | return False
198 |
199 | # Returns None if the topic is not a file, so only consider the topic
200 | # broken when the return is definitely false.
201 | if is_topic_file_valid(pkg_info, topic) is False:
202 | return False
203 |
204 | return True
205 |
206 | def is_enabled(self):
207 | return self.view.match_selector(0, "text.hyperhelp.help")
208 |
209 |
210 | ###----------------------------------------------------------------------------
211 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/resources/Context.sublime-menu.sublime-ignored:
--------------------------------------------------------------------------------
1 | [
2 | { "caption": "-", "id": "end" },
3 | { "command": "hyperhelp_context_create_bookmark" },
4 | { "caption": "-" },
5 | ]
6 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/resources/Default (Linux).sublime-keymap.sublime-ignored:
--------------------------------------------------------------------------------
1 | [
2 | // View the table of contents for the current help package.
3 | {
4 | "keys": ["?"], "command": "hyperhelp_contents",
5 | "context": [
6 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
7 | ]
8 | },
9 |
10 | // View the topic index for the current help package
11 | {
12 | "keys": ["i"], "command": "hyperhelp_index",
13 | "context": [
14 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
15 | ]
16 | },
17 |
18 | // Show the history of the help view in a quick panel and allow the user to
19 | // jump to a specific entry directly.
20 | {
21 | "keys": ["h"], "command": "hyperhelp_history",
22 | "args": {"action": "jump"},
23 | "context": [
24 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
25 | ]
26 | },
27 |
28 | // Prompt the user to bookmark the current file or topic.
29 | {
30 | "keys": ["b"],
31 | "command": "show_overlay",
32 | "args": {
33 | "overlay": "command_palette",
34 | "command": "hyperhelp_prompt_create_bookmark"
35 | },
36 | "context": [
37 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
38 | ]
39 | },
40 |
41 | // Prompt the user to select a bookmark, then navigate there.
42 | {
43 | "keys": ["g"],
44 | "command": "show_overlay",
45 | "args": {
46 | "overlay": "command_palette",
47 | "command": "hyperhelp_open_bookmark"
48 | },
49 | "context": [
50 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
51 | ]
52 | },
53 |
54 | // Navigate forward and backward through anchors in the current help file.
55 | {
56 | "keys": ["tab"], "command": "hyperhelp_navigate", "args": {
57 | "nav": "find_anchor",
58 | "prev": false,
59 | },
60 | "context": [
61 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
62 | ],
63 | },
64 | {
65 | "keys": ["shift+tab"], "command": "hyperhelp_navigate", "args": {
66 | "nav": "find_anchor",
67 | "prev": true,
68 | },
69 | "context": [
70 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
71 | ],
72 | },
73 |
74 | // Follow links in the current help file.
75 | {
76 | "keys": ["enter"], "command": "hyperhelp_navigate", "args": {
77 | "nav": "follow_link"
78 | },
79 | "context": [
80 | { "key": "selector", "operator": "equal", "operand": "text.hyperhelp.help meta.link" },
81 | { "key": "hyperhelp.is_authoring", "operator": "equal", "operand": false }
82 | ]
83 | },
84 | {
85 | "keys": ["keypad_enter"], "command": "hyperhelp_navigate", "args": {
86 | "nav": "follow_link"
87 | },
88 | "context": [
89 | { "key": "selector", "operator": "equal", "operand": "text.hyperhelp.help meta.link" },
90 | { "key": "hyperhelp.is_authoring", "operator": "equal", "operand": false }
91 | ]
92 | },
93 |
94 | // Navigate through the topic history
95 | {
96 | "keys": ["alt+left"], "command": "hyperhelp_history", "args": {
97 | "action": "prev"
98 | },
99 | "context": [
100 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
101 | ]
102 | },
103 | {
104 | "keys": ["alt+right"], "command": "hyperhelp_history", "args": {
105 | "action": "next"
106 | },
107 | "context": [
108 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
109 | ]
110 | },
111 |
112 | // Open the command palette with all help commands displayed.
113 | {
114 | "keys": ["super+h"], "command": "show_overlay",
115 | "args": {
116 | "overlay": "command_palette",
117 | "text" : "HyperHelp: "
118 | }
119 | }
120 | ]
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/resources/Default (OSX).sublime-keymap.sublime-ignored:
--------------------------------------------------------------------------------
1 | [
2 | // View the table of contents for the current help package.
3 | {
4 | "keys": ["?"], "command": "hyperhelp_contents",
5 | "context": [
6 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
7 | ]
8 | },
9 |
10 | // View the topic index for the current help package
11 | {
12 | "keys": ["i"], "command": "hyperhelp_index",
13 | "context": [
14 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
15 | ]
16 | },
17 |
18 | // Show the history of the help view in a quick panel and allow the user to
19 | // jump to a specific entry directly.
20 | {
21 | "keys": ["h"], "command": "hyperhelp_history",
22 | "args": {"action": "jump"},
23 | "context": [
24 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
25 | ]
26 | },
27 |
28 | // Prompt the user to bookmark the current file or topic.
29 | {
30 | "keys": ["b"], "command": "hyperhelp_prompt_create_bookmark",
31 | "context": [
32 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
33 | ]
34 | },
35 |
36 | // Prompt the user to select a bookmark, then navigate there.
37 | {
38 | "keys": ["g"], "command": "hyperhelp_open_bookmark",
39 | "context": [
40 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
41 | ]
42 | },
43 |
44 | // Navigate forward and backward through anchors in the current help file.
45 | {
46 | "keys": ["tab"], "command": "hyperhelp_navigate", "args": {
47 | "nav": "find_anchor",
48 | "prev": false,
49 | },
50 | "context": [
51 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
52 | ],
53 | },
54 | {
55 | "keys": ["shift+tab"], "command": "hyperhelp_navigate", "args": {
56 | "nav": "find_anchor",
57 | "prev": true,
58 | },
59 | "context": [
60 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
61 | ],
62 | },
63 |
64 | // Follow links in the current help file.
65 | {
66 | "keys": ["enter"], "command": "hyperhelp_navigate", "args": {
67 | "nav": "follow_link"
68 | },
69 | "context": [
70 | { "key": "selector", "operator": "equal", "operand": "text.hyperhelp.help meta.link" },
71 | { "key": "hyperhelp.is_authoring", "operator": "equal", "operand": false }
72 | ]
73 | },
74 | {
75 | "keys": ["keypad_enter"], "command": "hyperhelp_navigate", "args": {
76 | "nav": "follow_link"
77 | },
78 | "context": [
79 | { "key": "selector", "operator": "equal", "operand": "text.hyperhelp.help meta.link" },
80 | { "key": "hyperhelp.is_authoring", "operator": "equal", "operand": false }
81 | ]
82 | },
83 |
84 | // Navigate through the topic history
85 | {
86 | "keys": ["super+["], "command": "hyperhelp_history", "args": {
87 | "action": "prev"
88 | },
89 | "context": [
90 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
91 | ]
92 | },
93 | {
94 | "keys": ["super+]"], "command": "hyperhelp_history", "args": {
95 | "action": "next"
96 | },
97 | "context": [
98 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
99 | ]
100 | },
101 |
102 | // Open the command palette with all help commands displayed.
103 | {
104 | "keys": ["super+h"], "command": "show_overlay",
105 | "args": {
106 | "overlay": "command_palette",
107 | "text" : "HyperHelp: "
108 | }
109 | }
110 | ]
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/resources/Default (Windows).sublime-keymap.sublime-ignored:
--------------------------------------------------------------------------------
1 | [
2 | // View the table of contents for the current help package.
3 | {
4 | "keys": ["?"], "command": "hyperhelp_contents",
5 | "context": [
6 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
7 | ]
8 | },
9 |
10 | // View the topic index for the current help package
11 | {
12 | "keys": ["i"], "command": "hyperhelp_index",
13 | "context": [
14 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
15 | ]
16 | },
17 |
18 | // Show the history of the help view in a quick panel and allow the user to
19 | // jump to a specific entry directly.
20 | {
21 | "keys": ["h"], "command": "hyperhelp_history",
22 | "args": {"action": "jump"},
23 | "context": [
24 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
25 | ]
26 | },
27 |
28 | // Prompt the user to bookmark the current file or topic.
29 | {
30 | "keys": ["b"], "command": "hyperhelp_prompt_create_bookmark",
31 | "context": [
32 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
33 | ]
34 | },
35 |
36 | // Prompt the user to select a bookmark, then navigate there.
37 | {
38 | "keys": ["g"], "command": "hyperhelp_open_bookmark",
39 | "context": [
40 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
41 | ]
42 | },
43 |
44 | // Navigate forward and backward through anchors in the current help file.
45 | {
46 | "keys": ["tab"], "command": "hyperhelp_navigate", "args": {
47 | "nav": "find_anchor",
48 | "prev": false,
49 | },
50 | "context": [
51 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
52 | ],
53 | },
54 | {
55 | "keys": ["shift+tab"], "command": "hyperhelp_navigate", "args": {
56 | "nav": "find_anchor",
57 | "prev": true,
58 | },
59 | "context": [
60 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
61 | ],
62 | },
63 |
64 | // Follow links in the current help file.
65 | {
66 | "keys": ["enter"], "command": "hyperhelp_navigate", "args": {
67 | "nav": "follow_link"
68 | },
69 | "context": [
70 | { "key": "selector", "operator": "equal", "operand": "text.hyperhelp.help meta.link" },
71 | { "key": "hyperhelp.is_authoring", "operator": "equal", "operand": false }
72 | ]
73 | },
74 | {
75 | "keys": ["keypad_enter"], "command": "hyperhelp_navigate", "args": {
76 | "nav": "follow_link"
77 | },
78 | "context": [
79 | { "key": "selector", "operator": "equal", "operand": "text.hyperhelp.help meta.link" },
80 | { "key": "hyperhelp.is_authoring", "operator": "equal", "operand": false }
81 | ]
82 | },
83 |
84 | // Navigate through the topic history
85 | {
86 | "keys": ["alt+left"], "command": "hyperhelp_history", "args": {
87 | "action": "prev"
88 | },
89 | "context": [
90 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
91 | ]
92 | },
93 | {
94 | "keys": ["alt+right"], "command": "hyperhelp_history", "args": {
95 | "action": "next"
96 | },
97 | "context": [
98 | { "key": "hyperhelp.is_help_view", "operator": "equal", "operand": true },
99 | ]
100 | },
101 |
102 | // Open the command palette with all help commands displayed.
103 | {
104 | "keys": ["ctrl+alt+h"], "command": "show_overlay",
105 | "args": {
106 | "overlay": "command_palette",
107 | "text" : "HyperHelp: "
108 | }
109 | }
110 | ]
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/resources/HyperHelp-Help.sublime-settings.sublime-ignored:
--------------------------------------------------------------------------------
1 | {
2 | // Help files are standardized on 80 characters wide, but they should not
3 | // wrap.
4 | "wrap_width": 80,
5 | "word_wrap": false,
6 |
7 | // Remove visual clutter from the help view; authoring tools can apply
8 | // settings as required to edited views, or you can override these options
9 | // if desired in your own settings.
10 | "fade_fold_buttons": true,
11 | "match_selection": false,
12 | "draw_indent_guides": false,
13 | "rulers": [],
14 |
15 | // All help files should contain no physical tabs since there will never be
16 | // any concensus on how wide they should be.
17 | "detect_indentation": false,
18 | "translate_tabs_to_spaces": true
19 | }
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/resources/HyperHelp.sublime-commands.sublime-ignored:
--------------------------------------------------------------------------------
1 | [
2 | { "caption": "About HyperHelp", "command": "hyper_help_about" },
3 | { "caption": "HyperHelp ChangeLog", "command": "hyperhelp_topic", "args": { "package": "HyperHelp", "topic": "changelog.txt" } },
4 |
5 | { "caption": "HyperHelp: Help on Help", "command": "hyperhelp_topic", "args": { "package": "HyperHelp", "topic": "help_on_help.txt" } },
6 | { "caption": "HyperHelp: Browse Available Help", "command": "hyperhelp_contents", "args": { "prompt": true } },
7 | { "caption": "HyperHelp: Table of Contents", "command": "hyperhelp_contents", "args": { "prompt": false } },
8 | { "caption": "HyperHelp: Help Index", "command": "hyperhelp_index", "args": { "prompt": false } },
9 |
10 | { "caption": "HyperHelp: Open Bookmarked help topic", "command": "hyperhelp_open_bookmark" },
11 | { "caption": "HyperHelp: Create Bookmark", "command": "hyperhelp_prompt_create_bookmark" },
12 |
13 | { "caption": "HyperHelp: Clear topic history list", "command": "hyperhelp_history", "args": {"action": "clear" } },
14 | { "caption": "HyperHelp: Jump to topic in history list", "command": "hyperhelp_history", "args": {"action": "jump" } },
15 |
16 | {
17 | "caption": "Preferences: HyperHelp", "command": "edit_settings",
18 | "args":
19 | {
20 | "base_file": "${packages}/HyperHelp/resources/HyperHelp.sublime-settings",
21 | "default": "{\n\t$0\n}\n"
22 | }
23 | },
24 | {
25 | "caption": "Preferences: HyperHelp Key Bindings",
26 | "command": "edit_settings",
27 | "args":
28 | {
29 | "base_file": "${packages}/HyperHelp/resources/Default (${platform}).sublime-keymap",
30 | "default": "[\n\t$0\n]\n"
31 | }
32 | },
33 | ]
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/resources/HyperHelp.sublime-settings.sublime-ignored:
--------------------------------------------------------------------------------
1 | {
2 | // Specify the date format to be used for help dates in the loaded help
3 | // view. This uses the standard Python date format string formatting codes.
4 | "hyperhelp_date_format": "%x",
5 |
6 | // When HyperHelp is first installed and every time it's updated, it will
7 | // request that you restart Sublime to ensure that everything reloads
8 | // properly.
9 | //
10 | // If this setting is enabled, then on that restart HyperHelp will open and
11 | // display either its own changelog or the help on help topic.
12 | //
13 | // Disable this to not see the changelog (or the help on help, if you have
14 | // previously installed the package).
15 | "show_changelog": true,
16 |
17 | // When following a link, HyperHelp needs to display the correct help file
18 | // and ensure that the anchor is visible in the window. This setting
19 | // controls where the anchor will end up.
20 | //
21 | // When the value is true, the focused anchor will appear at the top of the
22 | // window, maximizing how much of the associated text you can see.
23 | //
24 | // When false, the anchor will be centered in the help view instead. This
25 | // was the default behaviour prior to this setting being introduced.
26 | "focus_links_at_top": true,
27 |
28 | // Specify a list of bookmarked help topics. These topics can be quickly
29 | // navigated to via the bookmark command in the command palette and the
30 | // main menu.
31 | "bookmarks": [
32 | ]
33 | }
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/resources/Main.sublime-menu.sublime-ignored:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "caption": "Preferences",
4 | "mnemonic": "n",
5 | "id": "preferences",
6 | "children":
7 | [
8 | {
9 | "caption": "Package Settings",
10 | "mnemonic": "P",
11 | "id": "package-settings",
12 | "children":
13 | [
14 | {
15 | "caption": "HyperHelp",
16 | "children":
17 | [
18 | {
19 | "caption": "Documentation",
20 | "command": "hyperhelp_topic",
21 | "args": {
22 | "package": "HyperHelp",
23 | "topic": "help_on_help.txt"
24 | }
25 | },
26 | {
27 | "caption": "View ChangeLog",
28 | "command": "hyperhelp_topic",
29 | "args": {
30 | "package": "HyperHelp",
31 | "topic": "changelog.txt"
32 | }
33 | },
34 | {
35 | "caption": "-"
36 | },
37 | {
38 | "caption": "Settings",
39 | "command": "edit_settings",
40 | "args": {
41 | "base_file": "${packages}/HyperHelp/resources/HyperHelp.sublime-settings",
42 | "default": "{\n\t$0\n}\n"
43 | }
44 | },
45 | {
46 | "caption": "Key Bindings",
47 | "command": "edit_settings",
48 | "args": {
49 | "base_file": "${packages}/HyperHelp/resources/Default ($platform).sublime-keymap",
50 | "default": "[\n\t$0\n]\n"
51 | }
52 | }
53 | ]
54 | }
55 | ]
56 | }
57 | ]
58 | },
59 |
60 | {
61 | "id": "help",
62 | "children":
63 | [
64 | {
65 | "id": "hyperhelp",
66 | "caption": "HyperHelp",
67 | "mnemonic": "y",
68 | "children": [
69 | {
70 | "caption": "Help on help",
71 | "command": "hyperhelp_topic",
72 | "args": {
73 | "package": "HyperHelp",
74 | "topic": "help_on_help.txt"
75 | }
76 | },
77 | {
78 | "caption": "Browse Available Help…",
79 | "command": "hyperhelp_contents",
80 | "args": { "prompt": true }
81 | },
82 |
83 | {
84 | "caption": "Create Bookmark…",
85 | "command": "hyperhelp_prompt_create_bookmark"
86 | },
87 | {
88 | "caption": "Open bookmarked help topic…",
89 | "command": "hyperhelp_open_bookmark"
90 | },
91 |
92 | { "caption": "-" },
93 |
94 | { "command": "hyperhelp_current_help" },
95 |
96 | { "caption": "-" },
97 |
98 | {
99 | "caption": "Table of Contents",
100 | "command": "hyperhelp_contents",
101 | },
102 | {
103 | "caption": "Help Index",
104 | "command": "hyperhelp_index",
105 | },
106 |
107 | { "caption": "-" },
108 |
109 | {
110 | "caption": "Clear topic history list",
111 | "command": "hyperhelp_history",
112 | "args": {
113 | "action": "clear"
114 | }
115 | },
116 |
117 | { "caption": "-" },
118 |
119 | {
120 | "caption": "Jump to item in history…",
121 | "command": "hyperhelp_history",
122 | "args": {
123 | "action": "jump"
124 | }
125 | },
126 | {
127 | "command": "hyperhelp_history",
128 | "args": {
129 | "action": "prev"
130 | }
131 | },
132 | {
133 | "command": "hyperhelp_history",
134 | "args": {
135 | "action": "next"
136 | }
137 | },
138 |
139 | { "caption": "-" },
140 |
141 | {
142 | "caption": "About HyperHelp",
143 | "command": "hyper_help_about",
144 | },
145 | {
146 | "caption": "View ChangeLog",
147 | "command": "hyperhelp_topic",
148 | "args": {
149 | "package": "HyperHelp",
150 | "topic": "changelog.txt"
151 | }
152 | }
153 | ]
154 | }
155 | ]
156 | }
157 | ]
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/resources/Preferences.sublime-settings-hints.sublime-ignored:
--------------------------------------------------------------------------------
1 | {
2 | // In normal operation, the help system will perform a bootstrap of the
3 | // HyperHelp package at startup if the package is missing or out of date.
4 | // In order to subvert this check and force a bootstrap to happen at every
5 | // startup, set this setting to true.
6 | //
7 | // This is intended for debugging and troubleshooting purposes.
8 | "hyperhelp.force_bootstrap": false,
9 |
10 | // The help system generates a warning at startup if the HyperHelp package
11 | // is in the list of ignored_packages, since this is an indications that the
12 | // last bootstrap did not complete successfully.
13 | //
14 | // You can disable the warning by changing the value of this setting to
15 | // true.
16 | "hyperhelp.ignore_disabled": false,
17 |
18 | // The help system generates a warning at startup if it detects a HyperHelp
19 | // folder in the Packages folder, since such a folder may contain overrides
20 | // that can cause issues such as masking updates.
21 | //
22 | // If you understand the ramifications of overriding the help system, you
23 | // can disable the warning by setting this setting to true.
24 | "hyperhelp.allow_unpacked": false,
25 | }
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/resources/Symbol List - Exclusions.tmPreferences.sublime-ignored:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | name
6 | Symbol List: Discard Inline Python
7 | scope
8 | text.hyperhelp.help source.python meta.function - meta.function.inline, text.hyperhelp.help source.python meta.class
9 | settings
10 |
11 | showInSymbolList
12 | 0
13 |
14 |
15 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/resources/Symbol List - Headers.tmPreferences.sublime-ignored:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | name
6 | Symbol List: Section Headers
7 | scope
8 | text.hyperhelp.help meta.heading.anchor
9 | settings
10 |
11 | showInSymbolList
12 | 1
13 | symbolTransformation
14 |
19 |
20 | uuid
21 | c484f41d-5700-48ba-a93e-facea4b9dee2
22 |
23 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/resources/Symbol List - Title.tmPreferences.sublime-ignored:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | name
6 | Symbol List: Document Title
7 | scope
8 | text.hyperhelp.help meta.help.header meta.title
9 | settings
10 |
11 | showInSymbolList
12 | 1
13 | symbolTransformation
14 |
18 |
19 | uuid
20 | c484f41d-5700-48ba-a93e-facea4b9dee2
21 |
22 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/resources/syntax/HyperHelp-Help.sublime-syntax.sublime-ignored:
--------------------------------------------------------------------------------
1 | %YAML 1.2
2 | ---
3 | name: Help
4 | scope: text.hyperhelp.help
5 | first_line_match: '^%hyperhelp'
6 | hidden: true
7 | variables:
8 | block_markup: '^\s*(`{3})(?![^`]*`)'
9 | block_markup_end: '^\s*(`{3})\s*$'
10 | separator: '(?:(?:\+|\|)?([=-])\1{3,}(?:\+|\|)?)|(?:\|)'
11 |
12 | contexts:
13 | main:
14 | - include: help-header
15 | - include: help-source-header
16 | - match: ''
17 | set: body
18 | help-header:
19 | - match: '^(\*)([^*\|]+)(\*)\s+(.*?)\s{2,}(.*)'
20 | captures:
21 | 0: meta.help.header
22 | 1: string.unquoted punctuation.anchor.begin
23 | 2: string.unquoted meta.anchor
24 | 3: string.unquoted punctuation.anchor.end
25 | 4: storage.type.class meta.title
26 | 5: variable.language meta.date
27 | set: body
28 | help-source-header:
29 | - match: '^(%)(hyperhelp)'
30 | captures:
31 | 1: punctuation.definition.directive
32 | 2: keyword.other.directive meta.directive
33 | push: header-keypairs
34 | header-keypairs:
35 | - match: '\b([a-z]+)(=)(")([^"]*)(")'
36 | captures:
37 | 1: storage.type.class meta.key
38 | 2: keyword.operator
39 | 3: string.quoted.double
40 | 4: string.quoted.double meta.value
41 | 5: string.quoted.double
42 | - match: '\S'
43 | scope: invalid.illegal.hyperhelp.header
44 | - match: '$'
45 | set: body
46 | comments:
47 | - match: '<\*\*'
48 | scope: punctuation.definition.comment.begin.help
49 | push:
50 | - meta_scope: comment.block.help
51 | - match: '(\*\*>)(\n)?'
52 | captures:
53 | 1: punctuation.definition.comment.end.help
54 | pop: true
55 | key-bindings:
56 | - match: '<(?=[>\w?])'
57 | scope: variable.language punctuation.definition.keybind.begin.help
58 | push:
59 | - meta_scope: variable.language meta.keybind
60 | - match: '>(?=[^>])'
61 | pop: true
62 | inline-code-block:
63 | - match: '`'
64 | scope: punctuation.definition.raw.begin
65 | push:
66 | - meta_content_scope: markup.raw.inline
67 | - match: '`'
68 | scope: punctuation.definition.raw.end
69 | pop: true
70 | code-blocks:
71 | - match: '{{block_markup}}(json).*$\n?'
72 | captures:
73 | 0: meta.code-fence.definition.begin.json
74 | 1: punctuation.definition.code-fence.begin.json
75 | 2: constant.other.language-name
76 | embed: scope:source.json
77 | embed_scope: markup.raw.code-fence.json
78 | escape: '{{block_markup_end}}'
79 | escape_captures:
80 | 0: meta.code-fence.definition.end.json
81 | 1: punctuation.definition.code-fence.end.json
82 | - match: '{{block_markup}}(python|py).*$\n?'
83 | captures:
84 | 0: meta.code-fence.definition.begin.python
85 | 1: punctuation.definition.code-fence.begin.python
86 | 2: constant.other.language-name
87 | embed: scope:source.python
88 | embed_scope: markup.raw.code-fence.python
89 | escape: '{{block_markup_end}}'
90 | escape_captures:
91 | 0: meta.code-fence.definition.end.python
92 | 1: punctuation.definition.code-fence.end.python
93 | - match: '{{block_markup}}(xml|plist).*$\n?'
94 | captures:
95 | 0: meta.code-fence.definition.begin.xml
96 | 1: punctuation.definition.code-fence.begin.xml
97 | 2: constant.other.language-name
98 | embed: scope:text.xml
99 | embed_scope: markup.raw.code-fence.xml
100 | escape: '{{block_markup_end}}'
101 | escape_captures:
102 | 0: meta.code-fence.definition.end.xml
103 | 1: punctuation.definition.code-fence.end.xml
104 | - match: '{{block_markup}}([\w-]*).*$\n?'
105 | captures:
106 | 0: meta.code-fence.definition.begin
107 | 1: punctuation.definition.code-fence.begin
108 | 2: constant.other.language-name
109 | push:
110 | - meta_content_scope: markup.raw.code-fence
111 | - match: '{{block_markup_end}}'
112 | captures:
113 | 0: meta.code-fence.definition.end
114 | 1: punctuation.definition.code-fence.end
115 | pop: true
116 | links:
117 | - match: '\|(?=[\w:$])'
118 | scope: storage punctuation.link.begin
119 | push:
120 | - meta_content_scope: storage meta.link
121 | - match: '\|'
122 | scope: storage punctuation.link.end
123 | pop: true
124 | anchors:
125 | - match: '\*(?=[\w:$])'
126 | scope: string.unquoted punctuation.anchor.begin
127 | push:
128 | - meta_content_scope: string.unquoted meta.anchor
129 | - match: '\*'
130 | scope: string.unquoted punctuation.anchor.end
131 | pop: true
132 | - match: '\*\|(?=[\w:$])'
133 | scope: string.unquoted punctuation.anchor.hidden.begin
134 | push:
135 | - meta_content_scope: string.unquoted meta.anchor.hidden
136 | - match: '\|\*'
137 | scope: string.unquoted punctuation.anchor.hidden.end
138 | pop: true
139 | - match: '^\s*(?=#)'
140 | push: header-anchors
141 | header-anchor-terminator:
142 | - match: '[ ]*(#*)[ ]*($\n?)'
143 | captures:
144 | 1: string.unquoted punctuation.anchor.end.heading
145 | pop: true
146 | header-anchors:
147 | - match: '(#)(?!#)\s*(?=\S)'
148 | captures:
149 | 1: string.unquoted punctuation.anchor.begin.heading
150 | set:
151 | - meta_scope: meta.heading.anchor
152 | - meta_content_scope: string.unquoted meta.anchor.heading.1
153 | - include: header-anchor-terminator
154 | - match: '(##)(?!#)\s*(?=\S)'
155 | captures:
156 | 1: string.unquoted punctuation.anchor.begin.heading
157 | set:
158 | - meta_scope: meta.heading.anchor
159 | - meta_content_scope: string.unquoted meta.anchor.heading.2
160 | - include: header-anchor-terminator
161 | - match: '(#{3,})(?!#)\s*(?=\S)'
162 | captures:
163 | 1: string.unquoted punctuation.anchor.begin.heading
164 | set:
165 | - meta_scope: meta.heading.anchor
166 | - meta_content_scope: string.unquoted meta.anchor.heading.3
167 | - include: header-anchor-terminator
168 | - match: ''
169 | pop: true
170 | separators:
171 | - match: '{{separator}}'
172 | scope: storage meta.separator
173 | body:
174 | - include: comments
175 | - include: key-bindings
176 | - include: code-blocks
177 | - include: inline-code-block
178 | - include: links
179 | - include: anchors
180 | - include: separators
181 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/resources/syntax/HyperHelp-Index.sublime-syntax.sublime-ignored:
--------------------------------------------------------------------------------
1 | %YAML 1.2
2 | ---
3 | name: Help Index
4 | scope: text.hyperhelp.index
5 | hidden: true
6 | file_extensions:
7 | - hyperhelp.json
8 |
9 | contexts:
10 | main:
11 | - include: scope:source.json
12 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/HyperHelp/resources/syntax/HyperHelpComments.tmPreferences.sublime-ignored:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | name
5 | Comments
6 | scope
7 | text.hyperhelp.index
8 | settings
9 |
10 | shellVariables
11 |
12 |
13 | name
14 | TM_COMMENT_START
15 | value
16 | //
17 |
18 |
19 | name
20 | TM_COMMENT_START_2
21 | value
22 | /*
23 |
24 |
25 | name
26 | TM_COMMENT_END_2
27 | value
28 | */
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/__init__.py:
--------------------------------------------------------------------------------
1 | ### ---------------------------------------------------------------------------
2 |
3 |
4 | from .startup import initialize
5 |
6 | __version_tuple = (0, 0, 8)
7 | __version__ = ".".join([str(num) for num in __version_tuple])
8 |
9 |
10 | ### ---------------------------------------------------------------------------
11 |
12 |
13 | __all__ = [
14 | "common",
15 | "core",
16 | "data",
17 | "help",
18 | "initialize",
19 | "version"
20 | "view",
21 | ]
22 |
23 |
24 | ### ---------------------------------------------------------------------------
25 |
26 |
27 | def version():
28 | """
29 | Get the version of the installed dependency package as a tuple. This is
30 | used during the bootstrap check to see if the version of the dependency has
31 | changed.
32 | """
33 | return __version_tuple
34 |
35 |
36 | ### ---------------------------------------------------------------------------
--------------------------------------------------------------------------------
/all/hyperhelpcore/bootstrapper.py:
--------------------------------------------------------------------------------
1 | import sublime
2 |
3 | import os
4 | import re
5 | import codecs
6 | import textwrap
7 | from zipfile import ZipFile
8 |
9 | from threading import Thread
10 |
11 | from os.path import join, dirname, normpath, relpath
12 | from importlib import __import__ as do_import
13 |
14 |
15 | ### ---------------------------------------------------------------------------
16 |
17 |
18 | # These name the bootstrap package that we use to give Sublime access to our
19 | # resources and commands, and the base name of the file within that package
20 | # that is responsible for loading the commands into Sublime when the package
21 | # is loaded.
22 | bootstrap_pkg = "HyperHelp"
23 | bootloader = "bootstrap"
24 |
25 |
26 | ### ---------------------------------------------------------------------------
27 |
28 |
29 | def log(msg, *args, dialog=False, error=False, **kwargs):
30 | """
31 | Generate a message to the console and optionally as either a message or
32 | error dialog. The message will be formatted and dedented before being
33 | displayed, and will be prefixed with its origin.
34 | """
35 | msg = textwrap.dedent(msg.format(*args, **kwargs)).strip()
36 |
37 | if error:
38 | print("hyperhelp error:")
39 | return sublime.error_message(msg)
40 |
41 | for line in msg.splitlines():
42 | print("hyperhelp: {msg}".format(msg=line))
43 |
44 | if dialog:
45 | sublime.message_dialog(msg)
46 |
47 |
48 | def set_initial_topic(package, topic):
49 | """
50 | Set a setting in the active window that tells the bootstrapped package to
51 | open an initial help topic the next time the package loads.
52 | """
53 | settings = sublime.active_window().settings()
54 | settings.set("hyperhelp.initial_topic", "%s:%s" % (package, topic))
55 |
56 |
57 | def display_topic(package, topic):
58 | """
59 | Invoke the appropriate command to display the given help topic. The topic
60 | is presumed to be from our own package. This uses a timeout so that it can
61 | be invoked from within the bootstrap code.
62 | """
63 | sublime.set_timeout(lambda: sublime.run_command("hyperhelp_topic", {
64 | "package": package,
65 | "topic": topic
66 | }))
67 |
68 |
69 | ### ---------------------------------------------------------------------------
70 |
71 |
72 | class BootstrapThread(Thread):
73 | """
74 | Spawns a background thread that will create or update the hyperhelp
75 | bootstrap package.
76 | """
77 | def __init__(self):
78 | super().__init__()
79 | self.settings = sublime.load_settings("Preferences.sublime-settings")
80 |
81 |
82 | def enable_package(self, reenable_resources):
83 | """
84 | Enables the system bootstrap package (if it exists) by ensuring that
85 | it is not in the list of ignored packages and then restoring any
86 | resources that were unloaded back to the views that were using them.
87 | """
88 | ignored_packages = self.settings.get("ignored_packages", [])
89 |
90 | if bootstrap_pkg in ignored_packages:
91 | ignored_packages.remove(bootstrap_pkg)
92 | self.settings.set("ignored_packages", ignored_packages)
93 |
94 | # Enable resources after a short delay to ensure that Sublime has had a
95 | # change to re-index them.
96 | if reenable_resources:
97 | sublime.set_timeout_async(lambda: self.enable_resources())
98 |
99 |
100 | def disable_package(self):
101 | """
102 | Disables the system bootstrap package (if it exists) by ensuring that
103 | none of the resources that it provides are currently in use and then
104 | adding it to the list of ignored packages so that Sublime will unload
105 | it.
106 | """
107 | self.disable_resources()
108 |
109 | ignored_packages = self.settings.get("ignored_packages", [])
110 | if bootstrap_pkg not in ignored_packages:
111 | ignored_packages.append(bootstrap_pkg)
112 | self.settings.set("ignored_packages", ignored_packages)
113 |
114 |
115 | def enable_resources(self):
116 | """
117 | Enables all resources being provided by the system boostrap package by
118 | restoring the state that was saved when the resources were disabled.
119 | """
120 | for window in sublime.windows():
121 | for view in window.views():
122 | s = view.settings()
123 | old_syntax = s.get("_hh_boot_syntax", None)
124 | if old_syntax is not None:
125 | s.set("syntax", old_syntax)
126 | s.erase("_hh_boot_syntax")
127 |
128 |
129 | def disable_resources(self):
130 | """
131 | Disables all resources being provided by the system bootstrap package
132 | by saving the state of items that are using them and then reverting
133 | them to temporary defaults.
134 | """
135 | prefix = "Packages/{pkg}/".format(pkg=bootstrap_pkg)
136 |
137 | # TODO if the package also contains a custom color scheme, this should
138 | # also temporarily reset the color scheme back to defaults and then
139 | # restore them later.
140 | for window in sublime.windows():
141 | for view in window.views():
142 | s = view.settings()
143 | syntax = s.get("syntax")
144 | if syntax.startswith(prefix):
145 | s.set("_hh_boot_syntax", syntax)
146 | s.set("syntax", "Packages/Text/Plain text.tmLanguage")
147 |
148 |
149 | def create_boot_loader(self, stub_loader_name):
150 | """
151 | Given the name of a file containing a stub system bootstrap loader,
152 | return the body of a loader that contains the version number of the
153 | core dependency.
154 | """
155 | try:
156 | from hyperhelpcore import version as ver_info
157 |
158 | with codecs.open(stub_loader_name, 'r', 'utf-8') as file:
159 | content = file.read()
160 |
161 | return re.sub(r"^__core_version_tuple\s+=\s+\(.*\)$",
162 | "__core_version_tuple = {version}".
163 | format(version=str(ver_info())),
164 | content,
165 | count=1,
166 | flags=re.MULTILINE)
167 | except:
168 | log("Bootstrap error: Unable to create bootloader")
169 | raise
170 |
171 |
172 | def create_bootstrap_package(self, package, res_path):
173 | """
174 | Perform the task of actually creating the system bootstrap package from
175 | files in the given resource folder into the provided package.
176 | """
177 | try:
178 | success = True
179 | boot_file = "{file}.py".format(file=bootloader)
180 |
181 | with ZipFile(package, 'w') as zFile:
182 | for (path, dirs, files) in os.walk(res_path):
183 | rPath = relpath(path, res_path) if path != res_path else ""
184 |
185 | for file in files:
186 | real_file = join(res_path, path, file)
187 | archive_file = join(rPath, file)
188 |
189 | if archive_file.endswith(".sublime-ignored"):
190 | archive_file = archive_file[:-len(".sublime-ignored")]
191 |
192 | if archive_file == boot_file:
193 | content = self.create_boot_loader(real_file)
194 | zFile.writestr(archive_file, content)
195 | else:
196 | zFile.write(real_file, archive_file)
197 |
198 | except Exception as err:
199 | success = False
200 | log("Bootstrap error: {reason}", reason=str(err))
201 | if os.path.exists(package):
202 | os.remove(package)
203 |
204 | return success
205 |
206 |
207 | def run(self):
208 | """
209 | Creates or updates the system bootstrap package by packaging up the
210 | contents of the resource directory.
211 | """
212 | self.disable_package()
213 |
214 | res_path = normpath(join(dirname(__file__), bootstrap_pkg))
215 | package = join(sublime.installed_packages_path(), bootstrap_pkg +
216 | ".sublime-package")
217 |
218 | prefix = os.path.commonprefix([res_path, package])
219 | log("Bootstraping {path} to {pkg}",
220 | path=res_path[len(prefix):],
221 | pkg=package[len(prefix):])
222 |
223 | pkg_existed = os.path.isfile(package)
224 | success = self.create_bootstrap_package(package, res_path)
225 |
226 | self.enable_package(success)
227 |
228 | if not success:
229 | return log(
230 | """
231 | An error was encountered while updating HyperHelp.
232 |
233 | Please check the console to see what went wrong.
234 | HyperHelp will not be available until the problem
235 | is resolved.
236 | """, error=True)
237 |
238 | if pkg_existed:
239 | set_initial_topic("HyperHelp", "latest_update")
240 | log(
241 | """
242 | HyperHelp has been updated!
243 |
244 | In order to complete the update, restart Sublime
245 | Text.
246 | """, dialog=True)
247 | else:
248 | # TODO: A restart should not be required here, but there are
249 | # currently bootstrap issues.
250 | set_initial_topic("HyperHelp", "help_on_help.txt")
251 | log(
252 | """
253 | HyperHelp has been installed!
254 |
255 | In order to complete the install, restart Sublime
256 | Text.
257 | """, dialog=True)
258 |
259 |
260 | ### ---------------------------------------------------------------------------
--------------------------------------------------------------------------------
/all/hyperhelpcore/common.py:
--------------------------------------------------------------------------------
1 | import sublime
2 |
3 | import os
4 | import codecs
5 |
6 | from .view import find_help_view
7 |
8 |
9 | ###----------------------------------------------------------------------------
10 |
11 |
12 | def log(message, *args, status=False, dialog=False):
13 | """
14 | Log the provided message to the console, optionally also sending it to the
15 | status bar and a dialog box.
16 | """
17 | message = message % args
18 | for line in message.splitlines():
19 | print("HyperHelp:", line)
20 | if status:
21 | sublime.status_message(message)
22 | if dialog:
23 | sublime.message_dialog(message)
24 |
25 |
26 | def hh_syntax(base_file):
27 | """
28 | Return the syntax file associated with the given base syntax file name.
29 | This can return None if the syntax is not known.
30 | """
31 | syn_list = sublime.find_resources(base_file)
32 | if len(syn_list) == 1:
33 | return syn_list[0]
34 |
35 | log("Unable to locate unique syntax '%s'", base_file)
36 |
37 |
38 | def hh_setting(key):
39 | """
40 | Get a HyperHelp setting from a cached settings object.
41 | """
42 | if not hasattr(hh_setting, "obj"):
43 | hh_setting.obj = sublime.load_settings("HyperHelp.sublime-settings")
44 | hh_setting.default = {
45 | "hyperhelp_date_format": "%x",
46 | "show_changelog": True,
47 | "focus_links_at_top": True,
48 | "bookmarks": []
49 | }
50 |
51 | default = hh_setting.default.get(key, None)
52 | return hh_setting.obj.get(key, default)
53 |
54 |
55 | def hh_update_setting(key, value, save=False):
56 | """
57 | Set the value of a HyperHelp setting to the value provided. Optionally, the
58 | call can also persist the change to disk.
59 | """
60 | hh_setting.obj.set(key, value)
61 | if save:
62 | sublime.save_settings("HyperHelp.sublime-settings")
63 |
64 |
65 | def load_resource(res_name):
66 | """
67 | Attempt to load and decode the UTF-8 encoded string with normalized line
68 | endings, returning the string on success or None on error.
69 |
70 | If no resource can be found with the resource specification provided, the
71 | call tries to load a file by this name from the packages folder instead.
72 | """
73 | try:
74 | text = sublime.load_binary_resource(res_name).decode("utf-8")
75 | return text.replace('\r\n', '\n').replace('\r', '\n')
76 |
77 | except OSError:
78 | pass
79 |
80 | except UnicodeError:
81 | return log("Unable to decode '%s'; resource is not UTF-8" % res_name)
82 |
83 | try:
84 | spp = os.path.split(sublime.packages_path())[0]
85 | file_name = os.path.join(spp, res_name)
86 |
87 | with codecs.open(file_name, 'r', 'utf-8') as file:
88 | return file.read().replace('\r\n', '\n').replace('\r', '\n')
89 |
90 | except OSError:
91 | return log("Unable to load '%s'; resource not found" % res_name)
92 |
93 | except UnicodeError:
94 | return log("Unable to decode '%s'; resource is not UTF-8" % res_name)
95 |
96 |
97 | def current_help_package(view=None, window=None):
98 | """
99 | Obtain the package that contains the currently displayed help file or None
100 | if help is not visible.
101 |
102 | Looks in the help view provided, or the help view in the passed in window,
103 | or the help view in the currently active window.
104 | """
105 | view = view or find_help_view(window)
106 | return (view.settings().get("_hh_pkg") if view is not None else None)
107 |
108 |
109 | def current_help_file(view=None, window=None):
110 | """
111 | Obtain the file that is currently being displayed in the help view or None
112 | if help is not visible.
113 |
114 | Looks in the help view provided, or the help view in the passed in window,
115 | or the help view in the currently active window.
116 | """
117 | view = view or find_help_view(window)
118 | return (view.settings().get("_hh_file") if view is not None else None)
119 |
120 |
121 | def help_package_prompt(help_list, on_select, on_cancel=None):
122 | """
123 | Given a list of loaded help indexes, prompt the user to select one of the
124 | packages. on_select is invoked with the name of the selected package,
125 | while on_cancel is invoked if the user cancels the selection.
126 | """
127 | if not help_list:
128 | return log("No packages with help are installed", status=True)
129 |
130 | pkg_list = sorted([key for key in help_list])
131 | captions = [[help_list[key].package,
132 | help_list[key].description]
133 | for key in pkg_list]
134 |
135 | def pick_package(index):
136 | package = None if index < 0 else captions[index][0]
137 |
138 | if index >= 0:
139 | return on_select(package) if on_select is not None else None
140 |
141 | return on_cancel() if on_cancel is not None else None
142 |
143 | sublime.active_window().show_quick_panel(
144 | captions,
145 | on_select=lambda index: pick_package(index))
146 |
147 |
148 | ###----------------------------------------------------------------------------
149 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/core.py:
--------------------------------------------------------------------------------
1 | import sublime
2 |
3 | import os
4 | import re
5 | import time
6 | import webbrowser
7 |
8 | from urllib.parse import urlparse
9 |
10 | from .common import log, hh_syntax, hh_setting
11 | from .view import find_help_view, update_help_view
12 |
13 | from .help_index import _load_help_index, _scan_help_packages
14 | from .help import _resource_for_help
15 | from .help import _load_help_file, _display_help_file, _reload_help_file
16 | from .help import HistoryData, _update_help_history
17 | from .data import HeaderData
18 |
19 |
20 | ###----------------------------------------------------------------------------
21 |
22 |
23 | _header_prefix_re = re.compile(r'^%hyperhelp(\b|$)')
24 | _header_keypair_re = re.compile(r'\b([a-z]+)\b="([^"]*)"')
25 |
26 |
27 | ###----------------------------------------------------------------------------
28 |
29 |
30 | def load_help_index(index_resource):
31 | """
32 | Given an index resource that points to a hyperhelp.json file, load the help
33 | index and return back a normalized version. Returns None on error.
34 | """
35 | return _load_help_index(index_resource)
36 |
37 |
38 | def load_help_file(pkg_info, help_file):
39 | """
40 | Load the contents of a help file contained in the provided help package.
41 | The help file should be relative to the document root of the package.
42 |
43 | Returns None if the help file cannot be loaded.
44 | """
45 | return _load_help_file(pkg_info, help_file)
46 |
47 |
48 | def help_index_list(reload=False, package=None):
49 | """
50 | Obtain or reload the help index information for all packages. This demand
51 | loads the indexes on first access and can optionally reload all package
52 | indexes or only a single one, as desired.
53 | """
54 | initial_load = False
55 | if not hasattr(help_index_list, "index"):
56 | initial_load = True
57 | help_index_list.index = _scan_help_packages()
58 |
59 | if reload and not initial_load:
60 | help_index_list.index = reload_help_index(help_index_list.index, package)
61 |
62 | return help_index_list.index
63 |
64 |
65 | def load_indexes_from_packages(packages):
66 | """
67 | Given a physical package name or list of names, load all help indexes that
68 | appear in that package and add them to the list of known help indexes. This
69 | implicitly loads all help indexes if they have never been loaded before.
70 | The new list of known help indexes is returned.
71 | """
72 | if not packages:
73 | return log("Cannot demand load package indexes; no packages provided")
74 |
75 | return _scan_help_packages(help_index_list(), packages)
76 |
77 |
78 | def unload_help_indexes_from_packges(packages):
79 | """
80 | Given a physical package name or list of names, unload any help indexes
81 | that are contained within that package. This implicitlly loads all help
82 | indexes if they have never been loaded before, and messages are printed to
83 | the console for each unloaded package. The new list of known help indexes
84 | is returned.
85 | """
86 | if not packages:
87 | return log("Cannot demand unload package indexes; no packages provided")
88 |
89 | if not isinstance(packages, list):
90 | packages = [packages]
91 |
92 | indexes = help_index_list()
93 | for pkg_info in list(indexes.values()):
94 | package = os.path.split(pkg_info.index_file)[0].split("/")[1]
95 | if package in packages:
96 | del indexes[pkg_info.package]
97 | log("Unloading help index for package '%s'", pkg_info.package)
98 |
99 | return indexes
100 |
101 |
102 | def reload_help_index(help_list, package):
103 | """
104 | Reload the help index for the provided package from within the given help
105 | list, updating the help list to record the new data.
106 |
107 | If no package name is provided, the help list provided is ignored and all
108 | help indexes are reloaded and returned in a new help list.
109 |
110 | Attempts to reload a package that is not in the given help list has no
111 | effect.
112 | """
113 | if package is None:
114 | log("Recanning all help index files")
115 | return _scan_help_packages()
116 |
117 | pkg_info = help_list.get(package, None)
118 | if pkg_info is None:
119 | log("Package '%s' was not previously loaded; cannot reload", package)
120 | else:
121 | log("Reloading help index for package '%s'", package)
122 |
123 | result = _load_help_index(pkg_info.index_file)
124 | if result is not None:
125 | help_list[result.package] = result
126 |
127 | # If the package changed from what it used to be, remove the old
128 | # one from the list of packages.
129 | if result.package != package:
130 | log("Warning: package name in index changed (%s became %s)",
131 | package, result.package)
132 | del help_list[package]
133 |
134 | return help_list
135 |
136 |
137 | def help_file_resource(pkg_info, help_file):
138 | """
139 | Get the resource name that references the help file in the given help
140 | package. The help file should be relative to the document root of the
141 | package.
142 | """
143 | return _resource_for_help(pkg_info, help_file)
144 |
145 |
146 | def display_help_file(pkg_info, help_file):
147 | """
148 | Load and display the help file contained in the provided help package. The
149 | heop file should be relative to the document root of the package.
150 |
151 | The help will be displayed in the help view of the current window, which
152 | will be created if it does not exist.
153 |
154 | Does nothing if the help view is already displaying this file.
155 |
156 | Returns None if the help file could not be found/loaded or the help view
157 | on success.
158 | """
159 | return _display_help_file(pkg_info, help_file)
160 |
161 |
162 | def reload_help_file(help_list, help_view):
163 | """
164 | Reload the help file currently being displayed in the given view to pick
165 | up changes made since it was displayed. The information on the package and
166 | help file should be contained in the provided help list.
167 |
168 | Returns True if the file was reloaded successfully or False if not.
169 | """
170 | return _reload_help_file(help_list, help_view)
171 |
172 |
173 | def lookup_help_topic(pkg_info, topic):
174 | """
175 | Given a help data tuple or the name of a package, look up the topic and
176 | return the topic structure if needed.
177 |
178 | This does all manipulations on the incoming topic, such as case folding and
179 | space replacement.
180 |
181 | Returns the topic structure or None.
182 | """
183 | if isinstance(pkg_info, str):
184 | pkg_info = help_index_list().get(pkg_info, None)
185 |
186 | if pkg_info is not None:
187 | topic = " ".join(topic.casefold().split())
188 | alias = pkg_info.help_aliases.get(topic, None)
189 | return pkg_info.help_topics.get(alias or topic, None)
190 |
191 | return None
192 |
193 |
194 | def is_topic_normal(pkg_info, topic_dict):
195 | """
196 | Given a topic dictionary such as returned by lookup_help_topic(), determine
197 | if the topic represents a "normal" topic or not.
198 | """
199 | return (not is_topic_url(pkg_info, topic_dict) and
200 | not is_topic_file(pkg_info, topic_dict))
201 |
202 |
203 | def is_topic_url(pkg_info, topic_dict):
204 | """
205 | Given a topic dictionary such as returned by lookup_help_topic(), determine
206 | if the topic represents a topic that will open a URL or not.
207 | """
208 | return topic_dict["file"] in pkg_info.urls
209 |
210 |
211 | def is_topic_file(pkg_info, topic_dict):
212 | """
213 | Given a topic dictionary such as returned by lookup_help_topic(), determine
214 | if the topic represents a topic that will open a URL or not.
215 | """
216 | return topic_dict["file"] in pkg_info.package_files
217 |
218 |
219 | def is_topic_url_valid(pkg_info, topic_dict):
220 | """
221 | Given a topic dictionary such as returned by lookup_help_topic() that
222 | represents a URL, return an indication as to whether the URL is valid or
223 | not.
224 |
225 | None is returned if a topic does not represent a URL.
226 | """
227 | if is_topic_url(pkg_info, topic_dict):
228 | try:
229 | result = urlparse(topic_dict["file"])
230 | return result.scheme and result.netloc
231 | except:
232 | return False
233 |
234 | return None
235 |
236 |
237 | def is_topic_file_valid(pkg_info, topic_dict):
238 | """
239 | Given a topic dictionary such as returned by lookup_help_topic() that
240 | represents a package file, return an indication as to whether that file
241 | exists or not as a package resource.
242 |
243 | None is returned if a topic does not represent a package file.
244 | """
245 | if is_topic_file(pkg_info, topic_dict):
246 | file = topic_dict["file"]
247 | base = os.path.split(file)[1]
248 | if file not in sublime.find_resources(base):
249 | return False
250 |
251 | return True
252 |
253 | return None
254 |
255 |
256 | def show_help_topic(package, topic, history):
257 | """
258 | Attempt to display the help for the provided topic in the given package
259 | (both strings) as appropriate. This will transparently create a new help
260 | view, open the underlying package file or open the URL as needed.
261 |
262 | If history is True, the history for the help view is updated after a
263 | successful help navigation to a help file; otherwise the history is left
264 | untouched. history is implicitly True when this has to create a help view
265 | for the first time so that history is properly initialized.
266 |
267 | The return value is None on error or a string that represents the kind of
268 | topic that was navigated to ("file", "pkg_file" or "url")
269 | """
270 | pkg_info = help_index_list().get(package, None)
271 | if pkg_info is None:
272 | return None
273 |
274 | topic_data = lookup_help_topic(pkg_info, topic)
275 | if topic_data is None:
276 | log("Unknown help topic '%s'", topic, status=True)
277 | return None
278 |
279 | help_file = topic_data["file"]
280 |
281 | if help_file in pkg_info.urls:
282 | webbrowser.open_new_tab(help_file)
283 | return "url"
284 |
285 | if help_file in pkg_info.package_files:
286 | help_file = help_file.replace("Packages/", "${packages}/")
287 | window = sublime.active_window()
288 | window.run_command("open_file", {"file": help_file})
289 | return "pkg_file"
290 |
291 | # Update the current history entry if there is a help view.
292 | if history:
293 | _update_help_history(find_help_view())
294 |
295 | existing_view = True if find_help_view() is not None else False
296 | help_view = display_help_file(pkg_info, help_file)
297 | if help_view is None:
298 | log("Unable to load help file '%s'", help_file, status=True)
299 | return None
300 |
301 | found = False
302 | anchor_dict = help_view.settings().get("_hh_nav", [])
303 | idx = anchor_dict.get(topic_data["topic"], -1)
304 | if idx >= 0:
305 | anchor_pos = help_view.get_regions("_hh_anchors")[idx]
306 | help_view.run_command("hyperhelp_focus",
307 | {
308 | "position": [anchor_pos.b, anchor_pos.a],
309 | "at_top": hh_setting("focus_links_at_top"),
310 | "at_center": not hh_setting("focus_links_at_top")
311 | })
312 | found = True
313 |
314 | # Update history to track the new file, but only if the help view already
315 | # existed; otherwise its creation set up the default history already.
316 | if history and existing_view:
317 | _update_help_history(help_view, append=True)
318 |
319 | if not found:
320 | log("Unable to find topic '%s' in help file '%s'", topic, help_file,
321 | status=True)
322 | return "file"
323 |
324 |
325 | def navigate_help_history(help_view, prev):
326 | """
327 | Navigate through the help history for the provided help view, either going
328 | forward or backward as appropriate. This will update the current history
329 | entry before displaying the historic topic.
330 |
331 | If no help view is provided, the current help view is used instead, if any.
332 |
333 | Returns a boolean to tell you if the history position changed or not.
334 | """
335 | help_view = help_view or find_help_view()
336 | if help_view is None:
337 | return False
338 |
339 | hist_pos = help_view.settings().get("_hh_hist_pos")
340 | hist_info = help_view.settings().get("_hh_hist")
341 |
342 | if (prev and hist_pos == 0) or (not prev and hist_pos == len(hist_info) - 1):
343 | log("Cannot navigate %s through history; already at the end",
344 | "backwards" if prev else "forwards", status=True)
345 | return False
346 |
347 | hist_pos = (hist_pos - 1) if prev else (hist_pos + 1)
348 | entry = HistoryData._make(hist_info[hist_pos])
349 |
350 | # Update the current history entry's viewport and caret location
351 | _update_help_history(help_view)
352 |
353 | # Navigate to the destination file in the history; need to manually set
354 | # the cursor position
355 | if show_help_topic(entry.package, entry.file, history=False) is not None:
356 | help_view.sel().clear()
357 | help_view.sel().add(sublime.Region(entry.caret[0], entry.caret[1]))
358 | help_view.set_viewport_position(entry.viewport, False)
359 |
360 | help_view.settings().set("_hh_hist_pos", hist_pos)
361 | return True
362 |
363 | return False
364 |
365 |
366 | def jump_help_history(help_view, new_pos):
367 | """
368 | Jump to a specific point in the help history for the provided help view.
369 |
370 | If no help view is provided, the current help view is used instead, if any.
371 |
372 | Returns a boolean to tell you if the history position changed or not; it
373 | may not change if the history index is not valid, for example.
374 | """
375 | help_view = help_view or find_help_view()
376 | if help_view is None:
377 | return False
378 |
379 | hist_pos = help_view.settings().get("_hh_hist_pos")
380 | hist_info = help_view.settings().get("_hh_hist")
381 |
382 | if new_pos < 0 or new_pos >= len(hist_info) or new_pos == hist_pos:
383 | return False
384 |
385 | entry = HistoryData._make(hist_info[new_pos])
386 |
387 | # Update the current history entry's viewport and caret location
388 | _update_help_history(help_view)
389 |
390 | # Navigate to the destination file in the history; need to manually set
391 | # the cursor position
392 | if show_help_topic(entry.package, entry.file, history=False) is not None:
393 | help_view.sel().clear()
394 | help_view.sel().add(sublime.Region(entry.caret[0], entry.caret[1]))
395 | help_view.set_viewport_position(entry.viewport, False)
396 |
397 | help_view.settings().set("_hh_hist_pos", new_pos)
398 | return True
399 |
400 |
401 | def clear_help_history(help_view):
402 | """
403 | Clear the help history for the provided help file, leaving only the current
404 | entry in the list as the sole history entry.
405 |
406 | If no help view is provided, the current help view is used instead, if any.
407 |
408 | Returns a boolean to tell you if history changed or not.
409 | """
410 | help_view = help_view or find_help_view()
411 | if help_view is None:
412 | return False
413 |
414 | hist_pos = help_view.settings().get("_hh_hist_pos")
415 | hist_info = help_view.settings().get("_hh_hist")
416 |
417 | entry = HistoryData._make(hist_info[hist_pos])
418 |
419 | help_view.settings().set("_hh_hist_pos", 0)
420 | help_view.settings().set("_hh_hist", [entry])
421 |
422 | return True
423 |
424 |
425 | def parse_help_header(help_file, header_line):
426 | """
427 | Given the first line of a help file, check to see if it looks like a help
428 | source file, and if so parse the header and return the parsed values back.
429 | """
430 | if not _header_prefix_re.match(header_line):
431 | return None
432 |
433 | title = "No Title Provided"
434 | date = 0.0
435 |
436 | for match in re.findall(_header_keypair_re, header_line):
437 | if match[0] == "title":
438 | title = match[1]
439 | elif match[0] == "date":
440 | try:
441 | date = time.mktime(time.strptime(match[1], "%Y-%m-%d"))
442 | except Exception as e:
443 | print(e)
444 | date = 0.0
445 | log("Ignoring invalid file date '%s' in '%s'",
446 | match[1], help_file)
447 | else:
448 | log("Ignoring unknown header key '%s' in '%s'",
449 | match[1], help_file)
450 |
451 | return HeaderData(help_file, title, date)
452 |
453 |
454 | def parse_anchor_body(anchor_body):
455 | """
456 | Given the body of an anchor, parse it to determine what topic ID it's
457 | anchored to and what text the anchor uses in the source help file.
458 |
459 | This always returns a 2-tuple, though based on the anchor body in the file
460 | it may end up thinking that the topic ID and the text are identical.
461 | """
462 | c_pos = anchor_body.find(':')
463 | if c_pos >= 0:
464 | id_val = anchor_body[:c_pos]
465 | anchor_body = anchor_body[c_pos+1:]
466 |
467 | id_val = id_val or anchor_body
468 | else:
469 | id_val = anchor_body
470 |
471 | return (id_val.casefold().rstrip(), anchor_body.strip())
472 |
473 |
474 | def parse_link_body(link_body):
475 | """
476 | Given the body of a link, parse it to determine what package and topic ID
477 | the link will navigate to as well as what the visual link text should be.
478 |
479 | This always returns a 3-tuple, though the value of the link text will be
480 | None if the parse failed. It's possible for the package to be None, in
481 | which case you can infer what the default package should be.
482 | """
483 | parts = link_body.split(':')
484 | if len(parts) == 1:
485 | return None, link_body.rstrip(), link_body.rstrip()
486 |
487 | if len(parts) >= 3:
488 | pkg = parts[0]
489 | topic = parts[1]
490 | text = ":".join(parts[2:])
491 | else:
492 | return (None, None, None)
493 |
494 | pkg = pkg or None
495 | topic = topic or text
496 | return (pkg, topic.strip(), text.strip())
497 |
498 |
499 | ###----------------------------------------------------------------------------
500 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/data.py:
--------------------------------------------------------------------------------
1 | from collections import OrderedDict, namedtuple
2 |
3 |
4 | ###----------------------------------------------------------------------------
5 |
6 |
7 | # A representation of the data that was contained in a hyperhelp help document
8 | # header. This is used to construct a more human readable header.
9 | HeaderData = namedtuple("HeaderData", [
10 | "file", "title", "date"
11 | ])
12 |
13 | # A representation of a history node that tracks what help topics have been
14 | # viewed and where the viewport was left.
15 | HistoryData = namedtuple("HistoryData", [
16 | "package", "file", "viewport", "caret"
17 | ])
18 |
19 | # A representation of all of the help available for a particular package.
20 | #
21 | # This tells us all of the information we need about the help for a package at
22 | # load time so that we don't need to look it up later.
23 | HelpData = namedtuple("HelpData", [
24 | "package", "index_file", "description", "doc_root", "help_topics",
25 | "help_aliases", "help_files", "package_files", "urls", "help_toc"
26 | ])
27 |
28 |
29 | ###----------------------------------------------------------------------------
30 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/help.py:
--------------------------------------------------------------------------------
1 | import sublime
2 | import sublime_plugin
3 |
4 | import re
5 | import time
6 |
7 | from .view import find_help_view, update_help_view
8 | from .common import log, hh_syntax, current_help_file, current_help_package
9 | from .common import load_resource
10 | from .data import HistoryData
11 |
12 |
13 | ###----------------------------------------------------------------------------
14 |
15 |
16 | def _resource_for_help(pkg_info, help_file):
17 | """
18 | Get the resource name that references the help file in the given help
19 | package. The help file should be relative to the document root of the
20 | package.
21 | """
22 | return "Packages/%s/%s" % (pkg_info.doc_root, help_file)
23 |
24 |
25 | def _load_help_file(pkg_info, help_file):
26 | """
27 | Load the contents of a help file contained in the provided help package.
28 | The help file should be relative to the document root of the package.
29 |
30 | Returns None if the help file cannot be loaded.
31 | """
32 | return load_resource(_resource_for_help(pkg_info, help_file))
33 |
34 |
35 | def _update_help_history(view, append=False, selection=None):
36 | """
37 | Update the help history for the provided view by either updating the
38 | contents of the current history entry or adding a new entry to the end of
39 | the history list.
40 |
41 | When appending a new history entry, any history after the current position
42 | in the list is truncated away.
43 |
44 | The selection used to capture the cursor is the first selection in the
45 | view unless a selection region is provided.
46 | """
47 | if view is None:
48 | return
49 |
50 | selection = view.sel()[0] if selection is None else selection
51 | settings = view.settings()
52 |
53 | hist_pos = settings.get("_hh_hist_pos", 0)
54 | hist_info = settings.get("_hh_hist", [])
55 |
56 | if append:
57 | # Truncate all history after this point; new timeline branches out.
58 | if hist_pos != len(hist_info) - 1:
59 | hist_info = hist_info[:hist_pos + 1]
60 |
61 | # Should probably truncate in the other direction to keep history in
62 | # check.
63 | hist_pos += 1
64 |
65 | history = HistoryData(current_help_package(view),
66 | current_help_file(view),
67 | view.viewport_position(),
68 | (selection.a, selection.b))
69 |
70 | if hist_pos >= len(hist_info):
71 | hist_info.append(history)
72 | else:
73 | hist_info[hist_pos] = history
74 |
75 | settings.set("_hh_hist_pos", hist_pos)
76 | settings.set("_hh_hist", hist_info)
77 |
78 |
79 | def _enable_post_processing(help_view, enable):
80 | """
81 | Enable or disable post processing on the provided help view, which controls
82 | whether or not the file can be edited and whether various post-processing
83 | commands are enabled.
84 | """
85 | help_view.set_read_only(not enable);
86 | help_view.settings().set("_hh_post_processing", enable)
87 |
88 |
89 | def _display_help_file(pkg_info, help_file):
90 | """
91 | Load and display the help file contained in the provided help package. The
92 | help file should be relative to the document root of the package.
93 |
94 | The help will be displayed in the help view of the current window, which
95 | will be created if it does not exist.
96 |
97 | Does nothing if the help view is already displaying this file.
98 |
99 | Returns None if the help file could not be found/loaded or the help view
100 | on success.
101 | """
102 | view = find_help_view()
103 | window = view.window() if view is not None else sublime.active_window()
104 |
105 | if view is not None:
106 | window.focus_view(view)
107 |
108 | current_pkg = current_help_package(view)
109 | current_file = current_help_file(view)
110 |
111 | if help_file == current_file and pkg_info.package == current_pkg:
112 | return view
113 |
114 | help_text = _load_help_file(pkg_info, help_file)
115 | if help_text is not None:
116 | view = update_help_view(help_text, pkg_info.package, help_file,
117 | hh_syntax("HyperHelp-Help.sublime-syntax"))
118 |
119 | # if there is no history yet, add one selection the start of the file.
120 | if not view.settings().has("_hh_hist_pos"):
121 | _update_help_history(view, selection=sublime.Region(0))
122 |
123 | _enable_post_processing(view, True)
124 | view.run_command("hyperhelp_internal_process_header")
125 | view.run_command("hyperhelp_internal_process_comments")
126 | view.run_command("hyperhelp_internal_process_anchors")
127 | view.run_command("hyperhelp_internal_process_links")
128 | _enable_post_processing(view, False)
129 |
130 | return view
131 |
132 | return log("Unable to find help file '%s'", help_file, status=True)
133 |
134 |
135 | def _reload_help_file(help_list, help_view):
136 | """
137 | Reload the help file currently being displayed in the given view to pick
138 | up changes made since it was displayed. The information on the package and
139 | help file should be contained in the provided help list.
140 |
141 | Returns True if the file was reloaded successfully or False if not.
142 | """
143 | if help_view is None:
144 | log("No help topic is visible; cannot reload")
145 | return False
146 |
147 | package = current_help_package(help_view)
148 | file = current_help_file(help_view)
149 | pkg_info = help_list.get(package, None)
150 |
151 | if pkg_info is not None and file is not None:
152 | # Remove the file setting so the view will reload; put it back if the
153 | # reload fails so we can still track what the file used to be.
154 | settings = help_view.settings()
155 | settings.set("_hh_file", "")
156 | if _display_help_file(pkg_info, file) is None:
157 | settings.set("_hh_file", file)
158 | return false
159 |
160 | return True
161 |
162 | log("Unable to reload the current help topic")
163 | return False
164 |
165 |
166 | def _get_link_topic(help_view, link_region):
167 | """
168 | Given a help view and information about a link, return back an object that
169 | provides the package and topic ID that the link references.
170 |
171 | region can be a Region object, in which case the link data is looked up by
172 | region. It can also be an integer, in which case it represents the index of
173 | that link, with the first link in the file being numbered as 0.
174 |
175 | None is returned when the information cannot be found.
176 | """
177 | topic_data = None
178 | topics = help_view.settings().get("_hh_links")
179 |
180 | try:
181 | # If the incoming region is an index, our job is easy.
182 | if isinstance(link_region, int):
183 | return topics[link_region]
184 |
185 | for idx, region in enumerate(help_view.get_regions("_hh_links")):
186 | if region == link_region:
187 | return topics[idx]
188 | except:
189 | pass
190 |
191 | return None
192 |
193 |
194 | ###----------------------------------------------------------------------------
195 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/help_index.py:
--------------------------------------------------------------------------------
1 | import sublime
2 | import sublime_plugin
3 |
4 | # Inside packages, paths are always posix regardless of the platform in use.
5 | import posixpath as path
6 | from collections import OrderedDict
7 | import os
8 | import re
9 | import codecs
10 |
11 | from .common import log, load_resource
12 | from .data import HelpData
13 | from .index_validator import validate_index
14 |
15 |
16 | ###----------------------------------------------------------------------------
17 |
18 |
19 | _url_prefix_re = re.compile(r'^https?://')
20 |
21 |
22 | ###----------------------------------------------------------------------------
23 |
24 |
25 | def _import_topics(package, topics, aliases, help_topic_dict, caption_tpl,
26 | external=False):
27 | """
28 | Parse out a dictionary of help topics from the help index and store all
29 | topics into the topic dictionary passed in. During the parsing, the
30 | contents are validated.
31 |
32 | When def_captions is True, topics that don't have a caption use the document
33 | title as the caption by default.
34 | """
35 | def _make_caption(topic, source):
36 | return caption_tpl.format(topic=topic, source=source, package=package)
37 |
38 | for help_source in help_topic_dict:
39 | topic_list = help_topic_dict[help_source]
40 |
41 | # Don't include topics from invalid externals.
42 | if (external
43 | and not _url_prefix_re.match(help_source)
44 | and not help_source.startswith("Packages/")):
45 | log("Discarding invalid external '%s' in %s",
46 | help_source, package)
47 | continue
48 |
49 | default_caption = topic_list[0] if external else None
50 |
51 | # Skip the first entry since it's the title of the help source
52 | for topic_entry in topic_list[1:]:
53 | name = topic_entry.get("topic")
54 | caption = topic_entry.get("caption", None)
55 | alias_list = topic_entry.get("aliases", [])
56 | if caption is None:
57 | caption = default_caption or _make_caption(name, help_source)
58 |
59 | # Normalize whitespace that appears in topics so that only a single
60 | # whitespace character appears wherever there might be two or more
61 | # in a row.
62 | # TODO: This could be a lot cleaner
63 | name = " ".join(name.casefold().split())
64 | if name in topics:
65 | log("Skipping duplicate topic '%s' in %s:%s",
66 | name, package, help_source)
67 | elif name in aliases:
68 | log("Topic %s is already an alias in %s:%s",
69 | name, package, help_source)
70 | else:
71 | topics[name] = {
72 | "topic": name,
73 | "caption": caption,
74 | "file": help_source
75 | }
76 |
77 | for new_name in [" ".join(name.casefold().split()) for name in alias_list]:
78 | if new_name in topics:
79 | log("Alias '%s' is already a topic in %s:%s",
80 | new_name, package, help_source)
81 | elif new_name in aliases:
82 | log("Skipping duplicate alias '%s' in %s:%s",
83 | new_name, package, help_source)
84 | else:
85 | aliases[new_name] = name
86 |
87 | # All help sources should be in the topic list so you can jump to a
88 | # file by name. The help file name is the default.
89 | name = help_source.casefold()
90 | if name not in topics:
91 | topics[name] = {
92 | "topic": name,
93 | "caption": topic_list[0],
94 | "file": help_source
95 | }
96 |
97 | return topics
98 |
99 |
100 | def _merge_externals(package, externals, topics, package_files, urls):
101 | """
102 | Merge the externals into the topic list provided. This ensures that there
103 | are no duplicate topics during the merge (discarding the external) while
104 | also splitting the externals into package file specifications and urls.
105 | """
106 | for topic, entry in externals.items():
107 | if topic in topics:
108 | log("Discarding duplicate external topic '%s' in %s:%s",
109 | topic, package, entry["file"])
110 | continue
111 |
112 | file = entry["file"]
113 | file_list = urls if _url_prefix_re.match(file) else package_files
114 | if file not in file_list:
115 | file_list.append(file)
116 |
117 | topics[topic] = entry
118 |
119 |
120 | def _get_file_metadata(help_topic_dict):
121 | """
122 | Parse a dictionary of help topics from the help index and return back an
123 | ordered dictionary associating help file names with their titles.
124 |
125 | Assumes the help dictionary has already been validated.
126 | """
127 | retVal = OrderedDict()
128 | for file in sorted(help_topic_dict.keys()):
129 | retVal[file] = help_topic_dict[file][0]
130 |
131 | return retVal
132 |
133 |
134 | def _get_toc_metadata(help_toc_list, topics, aliases, package):
135 | """
136 | Given the table of contents key from the help index and the complete list of
137 | known topics, return back a table of contents. This will extrapolate a list
138 | even if the incoming list is empty or non-existant.
139 | """
140 | if not help_toc_list:
141 | return [topics.get(topic) for topic in sorted(topics.keys())]
142 |
143 | def lookup_topic_entry(entry):
144 | """
145 | Expand a toc entry from the index into a full topic object.
146 | """
147 | if isinstance(entry, str):
148 | # A string looks up a topic directly; this goes through the alias
149 | # list if it has to.
150 | topic = aliases.get(entry, entry)
151 | return topic, topics.get(topic, None)
152 |
153 | # Use the caption for the topic being referenced if not overridden.
154 | topic = " ".join(entry["topic"].casefold().split())
155 | alias = aliases.get(topic, None)
156 | base_obj = topics.get(alias or topic, None)
157 | if base_obj is None:
158 | return topic, None
159 |
160 | entry["file"] = base_obj["file"]
161 | entry["caption"] = entry.get("caption", base_obj["caption"])
162 |
163 | return topic, entry
164 |
165 | def expand_topic_list(item_list):
166 | """
167 | Expand an array of help topics that make up part of a table of contents
168 | into an array of full topic objects recursively.
169 | """
170 | retVal = list()
171 |
172 | for item in item_list:
173 | topic, info = lookup_topic_entry(item)
174 | if info is None:
175 | log("TOC for '%s' is missing topic '%s'; skipping", package, topic)
176 | continue
177 |
178 | child_topics = info.get("children", None)
179 | if child_topics:
180 | info["children"] = expand_topic_list(child_topics)
181 |
182 | retVal.append(info)
183 |
184 | return retVal
185 |
186 | return expand_topic_list(help_toc_list)
187 |
188 |
189 | def _load_help_index(index_res):
190 | """
191 | Given a package name and the resource filename of the hyperhelp json file,
192 | load the help index and return it. The return value is None on failure or
193 | HelpData on success.
194 | """
195 | if not index_res.casefold().startswith("packages/"):
196 | return log("Index source is not in a package: %s", index_res)
197 |
198 | content = load_resource(index_res)
199 |
200 | if content is None:
201 | return log("Unable to load index information from '%s'", index_res)
202 |
203 | raw_dict = validate_index(content, index_res)
204 | if raw_dict is None:
205 | return None
206 |
207 | containing_pkg = path.split(index_res)[0].split("/")[1]
208 |
209 | # Top level index keys
210 | package = raw_dict.pop("package", None)
211 | description = raw_dict.pop("description", "Help for %s" % package)
212 | doc_root = raw_dict.pop("doc_root", None)
213 | help_files = raw_dict.pop("help_files", dict())
214 | help_toc = raw_dict.pop("help_contents", None)
215 | externals = raw_dict.pop("externals", None)
216 | caption_tpl = raw_dict.pop("default_caption",
217 | "Topic {topic} in help source {source}")
218 |
219 | # Warn if the dictionary has too many keys
220 | for key in raw_dict.keys():
221 | log("Ignoring unknown key '%s' in index file %s", key, package)
222 |
223 | # If there is no document root, set it from the index resource; otherwise
224 | # ensure that it's normalized to appear in the appropriate package.
225 | if not doc_root:
226 | doc_root = path.split(index_res[len("Packages/"):])[0]
227 | else:
228 | doc_root = path.normpath("%s/%s" % (containing_pkg, doc_root))
229 |
230 | # Gather the unique list of topics.
231 | topic_list = dict()
232 | alias_list = dict()
233 | _import_topics(package, topic_list, alias_list, help_files, caption_tpl)
234 |
235 | externals_list = dict()
236 | package_files = list()
237 | urls = list()
238 | if externals is not None:
239 | _import_topics(package, externals_list, alias_list, externals, caption_tpl, external=True)
240 | _merge_externals(package, externals_list, topic_list, package_files, urls)
241 |
242 | # Everything has succeeded.
243 | return HelpData(package, index_res, description, doc_root,
244 | topic_list, alias_list,
245 | _get_file_metadata(help_files), package_files, urls,
246 | _get_toc_metadata(help_toc, topic_list, alias_list, package))
247 |
248 |
249 | def _is_canonical_pkg_idx(pkg_idx):
250 | """
251 | Given a loaded package index, return a determination as to whether it is
252 | the canonical help for that package or not, which is determined by it being
253 | present in its own package.
254 | """
255 | containing_pkg = path.split(pkg_idx.index_file)[0].split("/")[1]
256 | return containing_pkg == pkg_idx.package
257 |
258 |
259 | def _resolve_index_conflict(existing_idx, new_idx):
260 | """
261 | Takes two loaded index files that are for the same package and selects one
262 | to use, which is returned back. The one selected is determined based on the
263 | load order of the indexes and user settings.
264 |
265 | The return may be None to indicate that neither package should be used.
266 | """
267 | existing_canon = _is_canonical_pkg_idx(existing_idx)
268 | new_canon = _is_canonical_pkg_idx(new_idx)
269 |
270 | log("Warning: Multiple indexes found for package '%s'", new_idx.package)
271 | log(" %s", existing_idx.index_file)
272 | log(" %s", new_idx.index_file)
273 |
274 | # When only one of the two packages is canonical, that is the one to use.
275 | if existing_canon != new_canon:
276 | if existing_canon:
277 | log("Warning: Ignoring non-canonical index (%s)", new_idx.index_file)
278 | return existing_idx
279 |
280 | log("Warning: Using canonical index (%s)", new_idx.index_file)
281 | return new_idx
282 |
283 | # The canon of both indexes is identical. If neither is canon, always use
284 | # the most recently loaded one (in package load order), just as result
285 | # Sublime resources would.
286 | if existing_canon == False:
287 | log("Warning: Selecting new index (%s)", new_idx.index_file)
288 | return new_idx
289 |
290 | # Both are canon, which is not good. This is an error, and we will return
291 | # None to signal that.
292 | log("Error: Multiple indexes for '%s' are canonical", new_idx.package)
293 | return None
294 |
295 |
296 | def _filter_index(resources, name_filter):
297 | """
298 | Filter a list of package index resources so that only indexes contained in
299 | the package(s) named are returned. When the filter is empty, the entire
300 | resource list is returned untouched. The filter can be a single package
301 | name or a list of packages.
302 | """
303 | if not name_filter:
304 | return resources
305 |
306 | if not isinstance(name_filter, list):
307 | name_filter = [name_filter]
308 |
309 | retVal = []
310 | for index_file in resources:
311 | path_parts = path.split(index_file)[0].split("/")
312 | if path_parts[0] == "Packages" and path_parts[1] in name_filter:
313 | retVal.append(index_file)
314 |
315 | return retVal
316 |
317 |
318 | def _scan_help_packages(help_list=None, name_filter=None):
319 | """
320 | Scan for packages with a help index and load them. If a help list is
321 | provided, only the help for packages not already in the list will be
322 | loaded.
323 | """
324 | help_list = dict() if help_list is None else help_list
325 |
326 | # Find all of the index file resources and the list of those that are
327 | # currently loaded in the provided help list (if any).
328 | indexes = _filter_index(sublime.find_resources("hyperhelp.json"), name_filter)
329 | loaded = [help_list[pkg].index_file for pkg in help_list.keys()]
330 |
331 | # The list of packages that are considered broken because they have at
332 | # least two canonical help indexes dedicated to them.
333 | broken = []
334 |
335 | # Load all of the indexes that aren't already loaded.
336 | for index_file in [idx for idx in indexes if idx not in loaded]:
337 | new_idx = _load_help_index(index_file)
338 | if new_idx is not None:
339 | # If this package index is broken, ignore it completely
340 | if new_idx.package in broken:
341 | log("Error: Ignoring index for '%s' (%s)", new_idx.package,
342 | new_idx.index_file)
343 | continue
344 |
345 | # If an index already exists for this package, we need to determine
346 | # which one to use.
347 | existing_idx = help_list.get(new_idx.package, None)
348 | if existing_idx is not None:
349 | # Returns None if both are canonical index files.
350 | new_idx = _resolve_index_conflict(existing_idx, new_idx)
351 | if new_idx is None:
352 | del help_list[existing_idx.package]
353 | broken.append(existing_idx.package)
354 | continue
355 |
356 | help_list[new_idx.package] = new_idx
357 |
358 | return help_list
359 |
360 |
361 | ###----------------------------------------------------------------------------
362 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/index_validator.py:
--------------------------------------------------------------------------------
1 | import sublime
2 |
3 | from .validictory import validate
4 | from .validictory import SchemaError, ValidationError
5 |
6 | from .common import log
7 |
8 |
9 | ###----------------------------------------------------------------------------
10 |
11 |
12 | # The schema to validate that a help file entry in the "help_files" key of the
13 | # help index is properly formattted.
14 | _help_file_schema = {
15 | "type": "object",
16 | "required": True,
17 |
18 | # Any key is allowed, but all must have values which are arrays. The first
19 | # item in the array must be a string and the remainder must be topic
20 | # dictionaries.
21 | "additionalProperties": {
22 | "type": "array",
23 | "items": [ { "type": "string", "required": True } ],
24 |
25 | "additionalItems": {
26 | "type": "object",
27 | "properties": {
28 | "topic": { "type": "string", "required": True },
29 | "caption": { "type": "string", "required": False },
30 | "aliases": {
31 | "type": "array",
32 | "items": { "type": "string", "required": True },
33 | "required": False
34 | }
35 | },
36 | "additionalProperties": False
37 | }
38 | }
39 | }
40 |
41 | # The schema to validate that the help table of contents in the "help_contents"
42 | # key of the help index is properly formattted.
43 | #
44 | # NOTE: This recursively references itself in the children element. See the
45 | # following line of code.
46 | _help_contents_schema = {
47 | "type": "array",
48 | "required": False,
49 |
50 | # Items must be topic dictionaries or strings. Topic dictionaries require
51 | # a topic key but may also contain a caption key and a children key which
52 | # is an array that is recursively identical to this one.
53 | #
54 | # Values that are strings are expanded to be topic dictionaries with no
55 | # children and an inherited caption.
56 | "items": {
57 | "type": [
58 | {"type": "string", "required": True },
59 | {
60 | "type": "object",
61 | "required": True,
62 | "properties": {
63 | "topic": { "type": "string", "required": True },
64 | "caption": { "type": "string", "required": False },
65 |
66 | # This is recursive; see below
67 | "children": "_help_contents_schema"
68 | },
69 | "additionalProperties": False
70 | }
71 | ]
72 | }
73 | }
74 |
75 | # The second type of item is a dictionary with a property that has the same
76 | # format as the top level key.
77 | _help_contents_schema["items"]["type"][1]["properties"]["children"] = _help_contents_schema
78 |
79 | # The schema to validate that the list of external resources in the "externals"
80 | # key of the help index is properly formatted.
81 | _externals_schema = {
82 | "type": "object",
83 | "required": False,
84 |
85 | # Any key is allowed, but all must have values which are arrays. The first
86 | # item in the array must be a string and the remainder must be topic
87 | # dictionaries.
88 | "additionalProperties": {
89 | "type": "array",
90 | "items": [ { "type": "string", "required": True } ],
91 |
92 | "additionalItems": {
93 | "type": "object",
94 | "properties": {
95 | "topic": { "type": "string", "required": True },
96 | "caption": { "type": "string", "required": False },
97 | "aliases": {
98 | "type": "array",
99 | "items": { "type": "string", "required": True },
100 | "required": False
101 | }
102 | },
103 | "additionalProperties": False
104 | }
105 | }
106 | }
107 |
108 | # The overall schema used to validate a hyperhelp index file.
109 | _index_schema = {
110 | "type": "object",
111 | "properties": {
112 | "package": { "type": "string", "required": True },
113 | "description": { "type": "string", "required": False },
114 | "doc_root": { "type": "string", "required": False },
115 | "default_caption": { "type": "string", "required": False },
116 |
117 | "help_files": _help_file_schema,
118 | "help_contents": _help_contents_schema,
119 | "externals": _externals_schema
120 | },
121 | "additionalProperties": False
122 | }
123 |
124 |
125 | ###----------------------------------------------------------------------------
126 |
127 |
128 | def validate_index(content, index_res):
129 | """
130 | Given a raw JSON string that represents a help index for a package, perform
131 | validation on it to ensure that it's valid JSON and also that it conforms
132 | to the appropriate index file help schema.
133 |
134 | Return a decoded dict object on success or None on failure.
135 | """
136 | def validate_fail(message, *args):
137 | log("Error validating index in '%s': %s", index_res, message % args)
138 |
139 | try:
140 | log("Loading help index from '%s'", index_res)
141 | raw_dict = sublime.decode_value(content)
142 | except:
143 | return validate_fail("Invalid JSON detected; unable to decode")
144 |
145 | try:
146 | validate(raw_dict, _index_schema)
147 | return raw_dict
148 |
149 | # The schema provided is itself broken.
150 | except SchemaError as error:
151 | return validate_fail("Invalid schema detected: %s", error)
152 |
153 | # One of the fields failed to validate. This generates extremely messy
154 | # output, but this can be fixed later.
155 | except ValidationError as error:
156 | return validate_fail("in %s: %s", error.fieldname, error)
157 |
158 | # Seems like validictory has a bug in which if you tell it to verify an
159 | # array has contents but the array is empty, it blows up. This can happen
160 | # if the array that provides the contents of a help file is empty, for
161 | # example.
162 | except Exception as error:
163 | return validate_fail("%s", error)
164 |
165 |
166 | ###----------------------------------------------------------------------------
167 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/startup.py:
--------------------------------------------------------------------------------
1 | import sublime
2 |
3 | import os
4 |
5 | from .bootstrapper import log, bootstrap_pkg, bootloader, BootstrapThread
6 |
7 |
8 | ### ---------------------------------------------------------------------------
9 |
10 |
11 | def _should_bootstrap(settings):
12 | """
13 | Check to see if the bootstrap package needs to be created/updated or not.
14 | This checks both for the existence of the package as well as for when the
15 | bootstrapped version is different from ours.
16 | """
17 | # For debugging/testing/troubleshooting purposes, this allows you to set a
18 | # setting that forces the bootstrap to occur, even if it doesn't need to be
19 | # done.
20 | if settings.get("hyperhelp.force_bootstrap", False):
21 | log("hyperhelp bootstrap forced; skipping check")
22 | return True
23 |
24 | try:
25 | from importlib import __import__ as do_import
26 | from hyperhelpcore import __version__ as mp_sys_version
27 |
28 | mod = do_import("{pkg}.{file}".format(
29 | pkg=bootstrap_pkg, file=bootloader),
30 | fromlist=("__version__"))
31 | bootstrapped_version = mod.__dict__["__version__"]
32 |
33 | if bootstrapped_version == mp_sys_version:
34 | msg = "hyperhelpcore system package {pkg_name} is up to date (v{sys})"
35 | else:
36 | msg = "upgrading hyperhelpcore system package {pkg_name} from v{boot} to v{sys}"
37 |
38 | log(msg, sys=mp_sys_version, boot=bootstrapped_version, pkg_name=bootstrap_pkg)
39 | return not bootstrapped_version == mp_sys_version
40 |
41 | except:
42 | log("hyperhelpcore system package is missing ({pkg_name}); bootstrapping",
43 | pkg_name=bootstrap_pkg)
44 |
45 | return True
46 |
47 |
48 | def initialize():
49 | """
50 | Ensures that the resource package that provides the syntax and other
51 | Sublime resources exists and is up to date; does nothing if this has
52 | already been called once.
53 |
54 | This *must* be invoked by all packages that are using hyperhelp actively
55 | and *must* be invoked after plugin_loaded() has been called, as it requires
56 | the Sublime API to be available.
57 | """
58 | if hasattr(initialize, "complete"):
59 | return
60 |
61 | initialize.complete = True
62 |
63 | settings = sublime.load_settings("Preferences.sublime-settings")
64 | ignored_packages = settings.get("ignored_packages", [])
65 |
66 | # Checks to see if the bootstrapped package is in the list of ignored
67 | # packages and complains if it is unless the user has also purposefully set
68 | # a setting telling us not to.
69 | #
70 | # This makes disabling the package a two step operation to stop potential
71 | # confusion on the behalf of the user, since they technically did not
72 | # install the bootstrapped package directly and might not know what it's
73 | # for.
74 | if bootstrap_pkg in ignored_packages:
75 | if settings.get("hyperhelp.ignore_disabled", False):
76 | return log("{pkg_name} package ignored; hyperhelp disabled",
77 | pkg_name=bootstrap_pkg)
78 |
79 | return log(
80 | """
81 | The {pkg_name} package is currently disabled.
82 |
83 | Please remove this package from the
84 | `ignored_packages` setting and restart Sublime.
85 |
86 | If your intention was to disable {pkg_name},
87 | set the value of the 'hyperhelp.ignore_disabled'
88 | setting to True in your Preferences.sublime-settings
89 | file to remove this warning message at startup.
90 | """, pkg_name=bootstrap_pkg, error=True)
91 |
92 | # If the boostrapped package is overridden, the user will block themselves
93 | # from getting updates when the dependency updates. So check if that is the
94 | # case and generate an error and refuse to proceed.
95 | #
96 | # An undocumented setting exists to turn this from an error to just a log
97 | # warning instead, in which case we proceed.
98 | pkg_folder = os.path.join(sublime.packages_path(), bootstrap_pkg)
99 | if os.path.lexists(pkg_folder):
100 | if settings.get("hyperhelp.allow_unpacked", False) == False:
101 | return log(
102 | """
103 | The {pkg_name} package is unpacked.
104 |
105 | This package should not be overridden as it
106 | blocks updates and causes problems with
107 | bootstrapping.
108 |
109 | Please remove the {pkg_name} folder from
110 | the Packages folder and restart sublime.
111 | """, pkg_name=bootstrap_pkg, error=True)
112 |
113 | log("hyperhelpcore system package {pkg_name} is unpacked; issues may arise",
114 | pkg_name=bootstrap_pkg)
115 |
116 | if _should_bootstrap(settings):
117 | BootstrapThread().start()
118 |
119 |
120 | ### ---------------------------------------------------------------------------
--------------------------------------------------------------------------------
/all/hyperhelpcore/validictory/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013 James Turk
2 |
3 | Contains code from jsonschema 0.2, copyright 2008 Ian Lewis, Yusuke Muraoka
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9 | of the Software, and to permit persons to whom the Software is furnished to do
10 | so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/validictory/__init__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | from .validator import (SchemaValidator, FieldValidationError, MultipleValidationError,
4 | ValidationError, SchemaError)
5 |
6 | __all__ = ['validate', 'SchemaValidator', 'FieldValidationError', 'MultipleValidationError',
7 | 'ValidationError', 'SchemaError']
8 | __version__ = '1.1.2'
9 |
10 |
11 | def validate(data, schema, validator_cls=SchemaValidator,
12 | format_validators=None, required_by_default=True,
13 | blank_by_default=False, disallow_unknown_properties=False,
14 | apply_default_to_data=False, fail_fast=True,
15 | remove_unknown_properties=False):
16 | '''
17 | Validates a parsed json document against the provided schema. If an
18 | error is found a :class:`ValidationError` is raised.
19 |
20 | If there is an issue in the schema a :class:`SchemaError` will be raised.
21 |
22 | :param data: python data to validate
23 | :param schema: python dictionary representing the schema (see
24 | `schema format`_)
25 | :param validator_cls: optional validator class (default is
26 | :class:`SchemaValidator`)
27 | :param format_validators: optional dictionary of custom format validators
28 | :param required_by_default: defaults to True, set to False to make
29 | ``required`` schema attribute False by default.
30 | :param disallow_unknown_properties: defaults to False, set to True to
31 | disallow properties not listed in the schema definition
32 | :param apply_default_to_data: defaults to False, set to True to modify the
33 | data in case the schema definition includes a "default" property
34 | :param fail_fast: defaults to True, set to False if you prefer to get
35 | all validation errors back instead of only the first one
36 | :param remove_unknown_properties: defaults to False, set to True to
37 | filter out properties not listed in the schema definition. Only applies
38 | when disallow_unknown_properties is False.
39 | '''
40 | v = validator_cls(format_validators, required_by_default, blank_by_default,
41 | disallow_unknown_properties, apply_default_to_data, fail_fast,
42 | remove_unknown_properties)
43 | return v.validate(data, schema)
44 |
45 | if __name__ == '__main__':
46 | import sys
47 | import json
48 | if len(sys.argv) == 2:
49 | if sys.argv[1] == "--help":
50 | raise SystemExit("%s SCHEMAFILE [INFILE]" % (sys.argv[0],))
51 | schemafile = open(sys.argv[1], 'rb')
52 | infile = sys.stdin
53 | elif len(sys.argv) == 3:
54 | schemafile = open(sys.argv[1], 'rb')
55 | infile = open(sys.argv[2], 'rb')
56 | else:
57 | raise SystemExit("%s SCHEMAFILE [INFILE]" % (sys.argv[0],))
58 | try:
59 | obj = json.load(infile)
60 | schema = json.load(schemafile)
61 | validate(obj, schema)
62 | except ValueError as e:
63 | raise SystemExit(e)
64 |
--------------------------------------------------------------------------------
/all/hyperhelpcore/view.py:
--------------------------------------------------------------------------------
1 | import sublime
2 |
3 |
4 | _get_window = lambda wnd: wnd if wnd is not None else sublime.active_window()
5 |
6 |
7 | ###----------------------------------------------------------------------------
8 |
9 |
10 | def find_help_view(window=None):
11 | """
12 | Search for and return the help view in the provided window. Defaults to
13 | searching the current window if none is provided.
14 | """
15 | window = window if window is not None else sublime.active_window()
16 | for view in window.views():
17 | if view.name().startswith("HyperHelp"):
18 | s = view.settings()
19 | if s.has("_hh_pkg") and s.has("_hh_file"):
20 | return view
21 |
22 |
23 | def new_help_view(syntax=None, window=None):
24 | """
25 | Create and return a new help view in the provided window. Defaults to the
26 | current window if none is specified.
27 | """
28 | hView = _get_window(window).new_file()
29 | hView.set_scratch(True)
30 | hView.set_name("HyperHelp")
31 |
32 | if syntax is not None:
33 | hView.assign_syntax(syntax)
34 |
35 | return hView
36 |
37 |
38 | def update_help_view(help_content, help_pkg, help_file,
39 | syntax=None, window=None):
40 | """
41 | Find or create the help view in the provided window and set it's contents
42 | to the help string provided. The help view will have it's internal state
43 | set up to track the given help package and file.
44 | """
45 | window = _get_window(window)
46 | help_view = find_help_view(window)
47 |
48 | if help_view is None:
49 | help_view = new_help_view(syntax, window)
50 | else:
51 | help_view.set_read_only(False)
52 | help_view.run_command("select_all")
53 | help_view.run_command("left_delete")
54 |
55 | if window.active_view() != help_view:
56 | window.focus_view(help_view)
57 |
58 | help_view.settings().set("_hh_pkg", help_pkg)
59 | help_view.settings().set("_hh_file", help_file)
60 |
61 | help_view.run_command("append", {"characters": help_content})
62 | help_view.set_read_only(True)
63 |
64 | return help_view
65 |
66 |
67 | ###----------------------------------------------------------------------------
68 |
--------------------------------------------------------------------------------