This package provides:
This package consumes:
Document outline and navigation panel. Navigate through custom section markers in text editors with tree view, filtering, and folding support.

navigation-adapter service. Used by pdf-viewer, image-editor, and jupyter-next.To install navigation-panel search for navigation-panel in the Install pane of the Pulsar settings or run ppm install navigation-panel. Alternatively, you can run ppm install asiloisad/pulsar-navigation-panel to install a package directly from the GitHub repository.
Commands available in atom-workspace:
navigation-panel:open: open navigation panel,navigation-panel:open-and-split-down: open navigation panel in split down,navigation-panel:hide: hide navigation panel,navigation-panel:toggle: toggle navigation panel,navigation-panel:toggle-focus: open and focus navigation panel, or return focus to editor if already focused,navigation-panel:list: open fuzzy modal list of current headers,navigation-panel:next-header: navigate to next visible header,navigation-panel:previous-header: navigate to previous visible header,navigation-panel:fold-toggle: toggle fold of current section,navigation-panel:fold-section: fold current section,navigation-panel:fold-section-at-N: fold last section at level N,navigation-panel:fold-as-table: fold all sections as table of contents,navigation-panel:fold-all-infos: fold all info sections,navigation-panel:fold-all-successes: fold all success sections,navigation-panel:fold-all-warnings: fold all warning sections,navigation-panel:fold-all-errors: fold all error sections,navigation-panel:unfold: unfold current section,navigation-panel:unfold-all: unfold all sections,navigation-panel:markers-toggle: toggle navigation markers.Commands available in .navigation-panel:
navigation-panel:search: focus search editor,navigation-panel:clear: clear search editor,navigation-panel:toggle-search-focus: toggle focus between search and header list,navigation-panel:select-previous-header: select previous header,navigation-panel:select-next-header: select next header,navigation-panel:collapse-selected-header: collapse selected header,navigation-panel:expand-selected-header: expand selected header,navigation-panel:open-selected-header: open selected header.Commands available in .navigation-panel-list:
select-list:open: navigate to selected header,select-list:scroll: scroll to selected header.This package provides a panel for navigating through custom symbols in text editors. The tree items are manually created by inserting special markers into the text editor. Multiple scopes are supported (see below) with their own marker system. The package supports multiple cursors.
The package introduces the concept of multi-level headers. The user enters a tag with a level, which indicates the maximum level of the text associated with that tag. The actual level of the header will be determined when building the header tree using the rule that a header can have a level at most one greater than its predecessor. For example, if you enter a level 1 heading, then a level 2 heading, and then a level 5 heading, the actual level of the last heading will be 3. The marker designations are for real headers. The real section level is used everywhere instead of the user level.
For each header, the package can create a marker to highlight the corresponding line of text in the editor. The marker style can be customized.
A panel has few handly commands. There are mouse interactions:
At context menu there are shortcuts to modify settings locally.
Headers can be filtered. Fuzzy-finder is used and items are sorted by score.
Headers can be marked with categories. The categories can be filtered in the bottom bar of the panel, the context menu of the panel, or using commands. The categories are predefined: info, success, warning, error. The meaning of the categories depends on the creativity of the user, so you can use them as you like.
The category settings can be changed globally in the package settings or locally using commands or in the panel:
navigation-panel:all-categories: activate all categoriesnavigation-panel:none-categories: deactivate all categoriesnavigation-panel:categories-toggle: toggle all categoriesnavigation-panel:info-toggle: toggle info category headersnavigation-panel:success-toggle: toggle success category headersnavigation-panel:warning-toggle: toggle warning category headersnavigation-panel:error-toggle: toggle error category headersnavigation-panel:standard-toggle: toggle category-less headersThe elements of the header tree can be collapsed, which can improve workflow or document clarity. The global settings can be changed in the package settings, and local settings can be adjusted using the context menu of the panel or through commands:
navigation-panel:collapse-mode: collapse all headers now and if rebuildingnavigation-panel:expand-mode: uncollapse all headers now and if rebuildingnavigation-panel:auto-collapse: expand only active headersThere are functions that provide folding actions (fold, unfold, or toggle) for sections. A special feature is the ability to collapse all sections to view them as a table of contents. You may be interested in the following commands:
navigation-panel:fold-toggle: toggle fold of current sectionnavigation-panel:fold-section: fold current sectionnavigation-panel:fold-section-at-n: fold last section at level nnavigation-panel:fold-as-table: fold all section but in nested formnavigation-panel:fold-all-infos: fold as table, but only headers with category infonavigation-panel:fold-all-successes: fold as table, but only headers with category successnavigation-panel:fold-all-warnings: fold as table, but only headers with category warningnavigation-panel:fold-all-errors: fold as table, but only headers with category errornavigation-panel:unfold: unfold current sectionnavigation-panel:unfold-all: unfold all sectionsIn order to search for markers in a text editor, all lines of the editor are tested using global regular expressions. If the global expression returns a positive search result, the matched lines are further processed. Global expressions can be found below, with different expressions for each scope.
You can test and analyze the regex patterns below on regex101. Just select the flavor as ECMAScript (JavaScript) and paste the statement.
The style can be adjusted according to user preferences in the styles.less file:
e.g. all markers have highlighted background, but only level 1, 2 and 3 have their own color:
.navigation-marker {
background: rgba(233, 228, 141, 0.3);
}
.navigation-marker-3 {
background: rgba(200, 197, 243, 0.3);
}
.navigation-marker-2 {
background: rgba(250, 192, 209, 0.3);
}
.navigation-marker-1 {
background: rgba(197, 218, 131, 0.3);
}
e.g. add top border to markers with level 1:
.navigation-marker-1 {
border-top: 0.016px solid @text-color-info;
}
e.g. change font to monospace:
.navigation-panel {
font-family: monospace;
}
e.g. change style of visible headers:
.navigation-panel .visible {
background: fade(green, 5%);
}
Global regular expression is ^(=={0,5}|#\#{0,5})[ \t]+(.+?)(?:[ \t]+\1)?$.
Global regular expression is ([^%\n]*)%(\$+)([\*\+\-\!\_]?)%(.*)|^[^\%\n]*\\(part*?|chapter*?|section*?|subsection*?|subsubsection*?|paragraph*?|subparagraph*?)\*?(?:\[(.*)\])?{(.*)}. The \part{...} is equal level 4, \chapter{...} is level 5 etc. The section commands can be changed in package settings.
%$!% Countries -> 1. Countries with error category%$$% United Kingdom -> 1.1. United Kingdom\part{Resources} -> 1.1.1.1. Resources\part[Resources]{Resources but to long to TOC} -> 1.1.1.1. ResourcesIn case of ([^%\n]*)%(\$+)%(.*), the additional letter can be used to provide additional visual effect:
*: info category+: success category-: warning category!: error category_: separator categoryGlobal regular expression is ([^%\n]*)%(\$+)([\*!-]?)%(.*)|^[ ]*\@(\w*)[ ]*{[ ]*([^\,]*). The @<type>{<text>, is level 6.
%$% Bibliography about countries -> 1. Bibliography about countries%$$% United Kingdom -> 1.1. United Kingdom@book{jk2021, ... -> 1.1.1.1.1.1. jk2021Additional letter can be used to provide additional visual effect:
*: info category+: success category-: warning category!: error category_: separator categoryGlobal regular expression is ^ *(\#+) (.*). The level is defined as count of #. The number of levels is endless.
# Countries -> 1. Countries### United Kingdom -> 1.1. United KingdomGlobal regular expression is (?:^(#+) +(.+?) *$|^ *(.+?) *: *$). The level is defined as count of #. The number of levels is endless. A header level is equal 5.
# Countries -> 1. Countries### United Kingdom -> 1.1. United KingdomUnited Kingdom: -> 1.1.1.1.1. United KingdomGlobal regular expression is ^([^#\n]*)#(?:%%)?(\$+[spv1]?|\?)([\*\+\-\!\_]?)#(.*) where count of $ mean the level on list. Headers are compatible with hydrogen-next cells.
Additional letter can be used to provide additional parse effect:
s: get only text from first string which occur at linep: python def or class; show only type and name of objectv: variable; show only name of variable1: use only first word (split by whitespace), without optional after-colonOne additional letter can be used to assign a category:
*: info category+: success category-: warning category!: error categoryAny additional letters can be used to provide additional visual effect:
_: separator line above the item<: increase font size;: font weight is boldAs special case you can use #?# or #?<category># which mean auto level base on pattern <any>(<lvl as int>, "<text>"<any>). It is useful e.g. in PyLaTex or similar.
#$# Countries -> 1. Countries#$$$# Countries -> 1. Countries and cell marker#$$# United Kingdom -> 1.1. United Kingdoma = 5 #$$v# -> 1.1. aclass MyCounty(Country): #$$p# -> 1.1. MyCountydocument.section(1, 'Countries') #?!# -> 1. Countriesdocument.section(2, 'United Kingdom') #?+# -> 1.1. United Kingdom with success categorydocument.section(2, 'United Kingdom') #?!# -> 1.1. United Kingdom with error categoryGlobal regular expression is ^([^\/\/\n]*)\/\/(\$+[sv1]?|\?)([\*\+\-\!\_]?)\/\/(.*) where count of $ mean the level on list.
Additional letter can be used to provide additional parse effect:
s: get only text from first string which occur at linev: variable; show only name of variable1: use only first word (split by whitespace)Additional letter can be used to provide additional visual effect:
*: info category+: success category-: warning category!: error category_: separator categoryAs special case you can use //?// or //?<category>// which mean auto level base on pattern <any>(<lvl as int>, "<text>"<any>).
//$// Countries -> 1. Countries//$$// United Kingdom -> 1.1. United Kingdoma = 5 //$$v// -> 1.1. adocument.section(1, 'Countries') //?!// -> 1. Countriesdocument.section(2, 'United Kingdom') //?+// -> 1.1. United Kingdom with success categorydocument.section(2, 'United Kingdom') //?!// -> 1.1. United Kingdom with error categoryGlobal regular expression is ^([^\/\/\n]*)\/\/(?:%%)?(\$+[scfv1]?|\?)([\*\+\-\!\_]?)\/\/(.*) where count of $ mean the level on list.
Additional letter can be used to provide additional parse effect:
s: get only text from first string which occur at linec: class, interface or enum; show only type and name of objectf: function; show function, const, let, var, or async declarationsv: variable; show only name of variable (const/let/var)1: use only first word (split by whitespace), without optional after-braceOne additional letter can be used to assign a category:
*: info category+: success category-: warning category!: error categoryAny additional letters can be used to provide additional visual effect:
_: separator line above the item<: increase font size;: font weight is boldAs special case you can use //?// or //?<category>// which mean auto level base on pattern <any>(<lvl as int>, "<text>"<any>).
//$// Main Section -> 1. Main Section//$$// Sub Section -> 1.1. Sub Sectionclass MyClass { //$c// Class definition -> 1. MyClassfunction myFunc() { //$f// Function -> 1. myFuncconst value = 10; //$$v// -> 1.1. valuedocument.section(1, 'Main') //?!// -> 1. Main with error categorydocument.section(2, 'Sub') //?+// -> 1.1. Sub with success categoryGlobal regular expression is ^(.+)\n([!-/:-@[-[-~])\2+$.
Global regular expression is ^ *(#define [^\n=]+$|#enddef)|^!([+-\\#\\$])!(?:chapter|kapitel) (.*)|(^(?! *\$)[^!\n]*)!(\$+)!(.*)|^ *([+-])?prog +([^\n]*)(?:\n *head +(.+))?|^ *!.! +(.*)|^\$ graphics +(\d+) +\| +picture +(\d+) +\| +layer +(\d+) +: *(.*). The chapter is equal level 4, prog is equal level 5 and label is equal level 6.
!$! Design slab -> 1. Design slab!$$! Req. reinforcement -> 1.1. Req. reinforcement!+!Chapter Design -> 1.1.1.1. Design+prog aqua -> 1.1.1.1.1. aqua+prog aqua \n head sections -> 1.1.1.1.1.1. aqua: head sectionsGlobal regular expression is:
^(`{3,})|^ *(=+) (.+)$
The level is defined as count of =. The number of levels is endless. Headings inside raw blocks (fenced with triple backticks) are skipped.
= Countries -> 1. Countries=== United Kingdom -> 1.1. United KingdomGlobal regular expression is ^;{2}[*+\-!]? (.+)$.
;;* TODOAdditional letter can be used to provide additional visual effect:
*: info category+: success category-: warning category!: error categorypdf-viewer provides its document outline via the navigation-adapter service. You can search the entire outline tree instead of the built-in PDFjs outline. A section number filter and scroll-position tracking are supported. Configure the filter in pdf-viewer settings (snoFilter).
image-editor provides its folder file list via the navigation-adapter service.
jupyter-next provides markdown cell headings via the navigation-adapter service. Clicking a heading activates the corresponding cell and scrolls to it.
navigation-adapterAllows external packages to provide navigation headers for any pane item type. When an adapter is registered and its handlesItem returns true for the active pane item, the panel displays headers provided by the adapter instead of running a built-in scanner.
In your package.json:
{
"providedServices": {
"navigation-adapter": {
"versions": {
"1.0.0": "provideNavigationAdapter"
}
}
}
}
In your main module:
module.exports = {
provideNavigationAdapter() {
return {
// Return true if this adapter handles the given pane item
handlesItem: (item) => item instanceof MyCustomEditor,
// Push a nested tree array initially and whenever headers or state change.
// Must return a Disposable.
observeHeaders: (item, callback) => {
callback(item.getNavigationHeaders(), { instant: true });
return item.onDidChangeNavigation(() => {
callback(item.getNavigationHeaders());
});
},
// Navigate to the given header.
// options.focus – false when scrolling without switching focus
// options.addCursor – true on Ctrl+click (add cursor, do not move)
navigateTo: (item, header, options) => item.revealHeader(header, options),
};
},
};
Header objects should have { text, level, classList, children }, where children is an array of child header objects. The adapter should build the nested structure and decide when to push a replacement tree. If the adapter tracks current or visible state, it should include that state directly on the pushed headers using currentCount / stackCount and visibility, or the public aliases current / active and visible.
The panel augments the tree with navigation callbacks and default display state, but it does not derive hierarchy from a flat list or compute adapter current/visible state.
Got ideas to make this package better, found a bug, or want to help add new features? Just drop your thoughts on GitHub. Any feedback is welcome!