Docs

Extending the Tree-View from Owned Packages

Pulsar’s tree-view exposes several extension points — context menus, file icons, and icon colors — all of which can be added from an owned package without touching tree-view itself.


Context menus

Context menu items are matched to right-click targets using CSS selectors. Multiple packages can target the same selector; their items are merged.

Static declaration (preferred)

Add entries to menus/<package-name>.json under "context-menu":

{
  "context-menu": {
    ".tree-view li.directory > .header": [
      { "label": "Open all URLs…", "command": "tranquil-browser:open-all-urls-in-folder" },
      { "type": "separator" }
    ],
    ".tree-view .file .name[data-name$='.url']": [
      { "label": "Open URL…", "command": "tranquil-browser:open-url-file" },
      { "type": "separator" }
    ]
  }
}

Then register the commands in activate() inside lib/<package>.js:

this.subscriptions.add(
  atom.commands.add('atom-workspace', {
    'tranquil-browser:open-url-file': function (event) {
      const entry = event.target.closest('.entry');
      const filePath = entry && entry.getPath();
      if (filePath) atom.workspace.open(filePath);
    },
  })
);

Dynamic registration

For conditional or runtime-generated items, use atom.contextMenu.add(). It returns a Disposable so items can be removed later.

const disposable = atom.contextMenu.add({
  '.tree-view li.directory > .header': [
    { label: 'My Action', command: 'my-package:my-action' }
  ]
});
// later: disposable.dispose();

Useful tree-view selectors

TargetSelector
Any directory header.tree-view li.directory > .header
Any file.tree-view [is="tree-view-file"]
File by extension.tree-view .file .name[data-name$='.url']
Project root header.tree-view .project-root > .header
Multi-select.tree-view .multi-select

Separators

Use { "type": "separator" } as an item to draw a divider line. Place one below your group to visually separate Tranquil items from native tree-view items.

Getting the clicked item’s path

Inside a command handler, retrieve the path of the right-clicked file or directory:

const entry = event.target.closest('.entry');
const filePath = entry && entry.getPath();

Both [is="tree-view-file"] and [is="tree-view-directory"] elements expose getPath().


File type icons

Tree-view consumes the atom.file-icons service (1.0.0). Providing this service from an owned package replaces the default icon logic entirely — the provider must handle all file types, not just the ones it cares about.

Declaring the service

In package.json:

"providedServices": {
  "atom.file-icons": {
    "versions": { "1.0.0": "provideFileIcons" }
  }
}

Implementing the provider

Delegate unknown extensions back to tree-view’s own DefaultFileIcons so only the target extension is customised:

provideFileIcons() {
  let defaultFileIcons = null;
  return {
    iconClassForPath(filePath) {
      if (typeof filePath === 'string' && filePath.endsWith('.url')) {
        return 'icon-globe';
      }
      if (!defaultFileIcons) {
        const pkg = atom.packages.getLoadedPackage('tree-view');
        if (pkg) defaultFileIcons = require(path.join(pkg.path, 'lib', 'default-file-icons'));
      }
      return defaultFileIcons ? defaultFileIcons.iconClassForPath(filePath) : 'icon-file-text';
    }
  };
}

Icon classes are Octicons — see static/variables/octicon-utf-codes.less for available names (icon-globe, icon-browser, icon-link, icon-file-text, etc.).

The provider lives in tranquil-theme-icons (../tranquil-theme-icons/lib/tranquil-theme-icons.js).


Icon colors and alignment

Icon glyphs are rendered via ::before pseudo-elements. Color and alignment can be set from any package’s Less stylesheet using ui-variables for theme-awareness.

@import "ui-variables";

.tree-view .name[data-name$=".url"]::before {
  color: @text-color-info;
  vertical-align: middle;
  position: relative;
  top: -1px;      /* glyph-specific vertical nudge — adjust per icon */
}

@text-color-info is the standard theme blue. Add rules per extension as new file types need colors. The stylesheet lives in tranquil-theme-icons (../tranquil-theme-icons/styles/tranquil-theme-icons.less).


Tree-view selection tracking (getPath)

Tree-view highlights a file entry when its pane item is active by calling getActivePaneItem().getPath() and matching the result against entries. If a custom pane item (e.g. TranquilBrowserModel) doesn’t implement getPath(), the entry is immediately deselected after opening.

Fix: implement getPath on the model

Store the source file path when the model is created from a file:

// in the opener
var model = new TranquilBrowserModel({
  tranquilBrowser: _this,
  url: url,
  filePath: filePath,   // the .url file path, not the web URL
  opt: {},
});
// in the model class
getPath() {
  return this.filePath;
}

Return null/undefined for models not backed by a file (e.g. opened directly from a URL) — tree-view will simply deselect in that case, which is correct.


Existing examples

FeaturePackageFile
Context menu (URL files + folders)tranquil-browsermenus/tranquil-browser.json
Context menu (markdown files)markdown-previewpackages/markdown-preview/menus/
Context menu (search in folder)find-and-replacepackages/find-and-replace/menus/
File icons + colorstranquil-theme-iconslib/, styles/
getPath on browser modeltranquil-browserlib/tranquil-browser-model.js