Socket
Socket
Sign inDemoInstall

nuclide-commons-atom

Package Overview
Dependencies
Maintainers
1
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

nuclide-commons-atom - npm Package Compare versions

Comparing version 0.1.3 to 0.1.4

ActiveEditorRegistry.js.flow

291

ActiveEditorRegistry.js

@@ -1,149 +0,87 @@

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
* @flow
* @format
*/
'use strict';
/**
* ActiveEditorRegistry provides abstractions for creating services that operate
* on text editor contents.
*/
Object.defineProperty(exports, "__esModule", {
value: true
});
import {Disposable} from 'atom';
import {Observable, Subject} from 'rxjs';
var _asyncToGenerator = _interopRequireDefault(require('async-to-generator'));
import {
observeActiveEditorsDebounced,
editorChangesDebounced,
} from './debounced';
var _atom = require('atom');
import {observableFromSubscribeFunction} from 'nuclide-commons/event';
import {cacheWhileSubscribed} from 'nuclide-commons/observable';
var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js');
import {getLogger} from 'log4js';
var _debounced;
import ProviderRegistry from './ProviderRegistry';
function _load_debounced() {
return _debounced = require('./debounced');
}
export type Provider = {
priority: number,
grammarScopes: Array<string>,
// This overrides the updateOnEdit setting in ActiveEditorRegistry's config.
updateOnEdit?: boolean,
};
var _event;
export type Result<T, V> =
| {
kind: 'not-text-editor',
}
| {
kind: 'no-provider',
grammar: atom$Grammar,
}
| {
kind: 'provider-error',
provider: T,
}
| {
// Since providers can be slow, the pane-change and edit events are emitted immediately in case
// the UI needs to clear outdated results.
kind: 'pane-change',
editor: atom$TextEditor,
}
| {
kind: 'edit',
editor: atom$TextEditor,
}
| {
kind: 'save',
editor: atom$TextEditor,
}
| {
kind: 'result',
result: V,
// The editor that the result was computed from
editor: atom$TextEditor,
// The provider that computed the result
// TODO Use a type paramater for this type
provider: T,
};
function _load_event() {
return _event = require('nuclide-commons/event');
}
export type ResultFunction<T, V> = (
provider: T,
editor: atom$TextEditor,
) => Promise<V>;
var _observable;
type PartialEventSources = {
+activeEditors?: Observable<?atom$TextEditor>,
+changesForEditor?: (editor: atom$TextEditor) => Observable<void>,
+savesForEditor?: (editor: atom$TextEditor) => Observable<void>,
};
function _load_observable() {
return _observable = require('nuclide-commons/observable');
}
export type EventSources = {
activeEditors: Observable<?atom$TextEditor>,
changesForEditor: (editor: atom$TextEditor) => Observable<void>,
savesForEditor: (editor: atom$TextEditor) => Observable<void>,
};
var _log4js;
export type Config = {
/**
* If true, we will query providers for updates whenever the text in the editor is changed.
* Otherwise, we will query only when there is a save event.
*/
updateOnEdit?: boolean,
};
function _load_log4js() {
return _log4js = require('log4js');
}
type ConcreteConfig = {
updateOnEdit: boolean,
};
var _ProviderRegistry;
const DEFAULT_CONFIG: ConcreteConfig = {
updateOnEdit: true,
};
function _load_ProviderRegistry() {
return _ProviderRegistry = _interopRequireDefault(require('./ProviderRegistry'));
}
function getConcreteConfig(config: Config): ConcreteConfig {
return {
...DEFAULT_CONFIG,
...config,
};
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const DEFAULT_CONFIG = {
updateOnEdit: true
}; /**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
*
* @format
*/
/**
* ActiveEditorRegistry provides abstractions for creating services that operate
* on text editor contents.
*/
function getConcreteConfig(config) {
return Object.assign({}, DEFAULT_CONFIG, config);
}
export default class ActiveEditorRegistry<T: Provider, V> {
_resultFunction: ResultFunction<T, V>;
_providerRegistry: ProviderRegistry<T>;
_newProviderEvents: Subject<void>;
_resultsStream: Observable<Result<T, V>>;
_config: ConcreteConfig;
class ActiveEditorRegistry {
constructor(
resultFunction: ResultFunction<T, V>,
config: Config = {},
eventSources: PartialEventSources = {},
) {
constructor(resultFunction, config = {}, eventSources = {}) {
this._config = getConcreteConfig(config);
this._resultFunction = resultFunction;
this._providerRegistry = new ProviderRegistry();
this._newProviderEvents = new Subject();
this._providerRegistry = new (_ProviderRegistry || _load_ProviderRegistry()).default();
this._newProviderEvents = new _rxjsBundlesRxMinJs.Subject();
this._resultsStream = this._createResultsStream({
activeEditors: eventSources.activeEditors ||
observeActiveEditorsDebounced(),
changesForEditor: eventSources.changesForEditor ||
(editor => editorChangesDebounced(editor)),
savesForEditor: eventSources.savesForEditor ||
(editor => {
return observableFromSubscribeFunction(callback =>
editor.onDidSave(callback),
).mapTo(undefined);
}),
activeEditors: eventSources.activeEditors || (0, (_debounced || _load_debounced()).observeActiveEditorsDebounced)(),
changesForEditor: eventSources.changesForEditor || (editor => (0, (_debounced || _load_debounced()).editorChangesDebounced)(editor)),
savesForEditor: eventSources.savesForEditor || (editor => {
return (0, (_event || _load_event()).observableFromSubscribeFunction)(callback => editor.onDidSave(callback)).mapTo(undefined);
})
});
}
consumeProvider(provider: T): IDisposable {
consumeProvider(provider) {
this._providerRegistry.addProvider(provider);
this._newProviderEvents.next();
return new Disposable(() => {
return new _atom.Disposable(() => {
this._providerRegistry.removeProvider(provider);

@@ -153,15 +91,12 @@ });

getResultsStream(): Observable<Result<T, V>> {
getResultsStream() {
return this._resultsStream;
}
_createResultsStream(eventSources: EventSources): Observable<Result<T, V>> {
_createResultsStream(eventSources) {
const repeatedEditors = eventSources.activeEditors.switchMap(editor => {
if (editor == null) {
return Observable.of(editor);
return _rxjsBundlesRxMinJs.Observable.of(editor);
}
return Observable.concat(
Observable.of(editor),
this._newProviderEvents.mapTo(editor),
);
return _rxjsBundlesRxMinJs.Observable.concat(_rxjsBundlesRxMinJs.Observable.of(editor), this._newProviderEvents.mapTo(editor));
});

@@ -172,31 +107,20 @@ const results = repeatedEditors.switchMap(editorArg => {

if (editor == null) {
return Observable.of({kind: 'not-text-editor'});
return _rxjsBundlesRxMinJs.Observable.of({ kind: 'not-text-editor' });
}
return Observable.concat(
// Emit a pane change event first, so that clients can do something while waiting for a
// provider to give a result.
Observable.of({
kind: 'pane-change',
editor,
}),
Observable.fromPromise(
this._getResultForEditor(this._getProviderForEditor(editor), editor),
),
this._resultsForEditor(editor, eventSources),
);
return _rxjsBundlesRxMinJs.Observable.concat(
// Emit a pane change event first, so that clients can do something while waiting for a
// provider to give a result.
_rxjsBundlesRxMinJs.Observable.of({
kind: 'pane-change',
editor
}), _rxjsBundlesRxMinJs.Observable.fromPromise(this._getResultForEditor(this._getProviderForEditor(editor), editor)), this._resultsForEditor(editor, eventSources));
});
return cacheWhileSubscribed(results);
return (0, (_observable || _load_observable()).cacheWhileSubscribed)(results);
}
_resultsForEditor(
editor: atom$TextEditor,
eventSources: EventSources,
): Observable<Result<T, V>> {
_resultsForEditor(editor, eventSources) {
// It's possible that the active provider for an editor changes over time.
// Thus, we have to subscribe to both edits and saves.
return Observable.merge(
eventSources.changesForEditor(editor).map(() => 'edit'),
eventSources.savesForEditor(editor).map(() => 'save'),
).flatMap(event => {
return _rxjsBundlesRxMinJs.Observable.merge(eventSources.changesForEditor(editor).map(() => 'edit'), eventSources.savesForEditor(editor).map(() => 'save')).flatMap(event => {
const provider = this._getProviderForEditor(editor);

@@ -210,45 +134,42 @@ if (provider != null) {

if (updateOnEdit !== (event === 'edit')) {
return Observable.empty();
return _rxjsBundlesRxMinJs.Observable.empty();
}
}
return Observable.concat(
// $FlowIssue: {kind: edit | save} <=> {kind: edit} | {kind: save}
Observable.of({kind: event, editor}),
Observable.fromPromise(this._getResultForEditor(provider, editor)),
);
return _rxjsBundlesRxMinJs.Observable.concat(
// $FlowIssue: {kind: edit | save} <=> {kind: edit} | {kind: save}
_rxjsBundlesRxMinJs.Observable.of({ kind: event, editor }), _rxjsBundlesRxMinJs.Observable.fromPromise(this._getResultForEditor(provider, editor)));
});
}
_getProviderForEditor(editor: atom$TextEditor): ?T {
_getProviderForEditor(editor) {
return this._providerRegistry.getProviderForEditor(editor);
}
async _getResultForEditor(
provider: ?T,
editor: atom$TextEditor,
): Promise<Result<T, V>> {
if (provider == null) {
return {
kind: 'no-provider',
grammar: editor.getGrammar(),
};
}
try {
return {
kind: 'result',
result: await this._resultFunction(provider, editor),
provider,
editor,
};
} catch (e) {
getLogger(this.constructor.name).error(
`Error from provider for ${editor.getGrammar().scopeName}`,
e,
);
return {
provider,
kind: 'provider-error',
};
}
_getResultForEditor(provider, editor) {
var _this = this;
return (0, _asyncToGenerator.default)(function* () {
if (provider == null) {
return {
kind: 'no-provider',
grammar: editor.getGrammar()
};
}
try {
return {
kind: 'result',
result: yield _this._resultFunction(provider, editor),
provider,
editor
};
} catch (e) {
(0, (_log4js || _load_log4js()).getLogger)(_this.constructor.name).error(`Error from provider for ${editor.getGrammar().scopeName}`, e);
return {
provider,
kind: 'provider-error'
};
}
})();
}
}
exports.default = ActiveEditorRegistry;

@@ -0,1 +1,9 @@

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _atom = require('atom');
/**

@@ -8,58 +16,37 @@ * Copyright (c) 2015-present, Facebook, Inc.

*
* @flow
*
* @format
*/
import type {Observable} from 'rxjs';
import {Disposable} from 'atom';
class NullTimingTracker {
constructor(name: string) {}
onError(error: Error) {}
constructor(name) {}
onError(error) {}
onSuccess() {}
}
type TrackingEvent = {
type: string,
data?: Object,
};
type TimingTrackerType = {
onError(error: Error): void,
onSuccess(): void,
};
const NullService = {
track(eventName: string, values?: {[key: string]: mixed}): void {},
trackEvent(event: TrackingEvent): void {},
trackEvents(events: Observable<TrackingEvent>): IDisposable {
return new Disposable();
track(eventName, values) {},
trackEvent(event) {},
trackEvents(events) {
return new _atom.Disposable();
},
trackImmediate(
eventName: string,
values?: {[key: string]: mixed},
): Promise<mixed> {
trackImmediate(eventName, values) {
return Promise.resolve();
},
startTracking(eventName: string): TimingTrackerType {
startTracking(eventName) {
return new NullTimingTracker(eventName);
},
trackTiming<T>(eventName: string, operation: () => T): T {
trackTiming(eventName, operation) {
return operation();
},
TimingTracker: NullTimingTracker,
TimingTracker: NullTimingTracker
};
let service = NullService;
atom.packages.serviceHub.consume(
'nuclide-analytics',
'0.0.0',
analyticsService => {
// es module export is a live binding, so modifying this updates the value
// for the consumer
service = analyticsService;
},
);
atom.packages.serviceHub.consume('nuclide-analytics', '0.0.0', analyticsService => {
// es module export is a live binding, so modifying this updates the value
// for the consumer
service = analyticsService;
});
export default service;
exports.default = service;

@@ -1,43 +0,9 @@

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
* @flow
* @format
*/
'use strict';
import {Disposable} from 'atom';
import invariant from 'assert';
Object.defineProperty(exports, "__esModule", {
value: true
});
type Item = {
type: 'item',
item: atom$ContextMenuItem,
priority: number,
};
var _atom = require('atom');
type Menu = {
type: 'menu',
menu: ContextMenu,
priority: number,
};
type InternalItem = Item | Menu;
type RootMenuOptions = {
type: 'root',
cssSelector: string,
};
type SubmenuOptions = {
type: 'submenu',
label: string,
parent: ContextMenu,
shouldDisplay?: (e: MouseEvent) => boolean,
};
type MenuOptions = RootMenuOptions | SubmenuOptions;
/**

@@ -58,4 +24,3 @@ * This class represents a collection of context menu items that have been registered with Atom's

*/
export default class ContextMenu {
_menuOptions: MenuOptions;
class ContextMenu {

@@ -67,16 +32,3 @@ /**

*/
_items: Array<InternalItem>;
_needsSort: boolean;
_sort: Function;
/**
* This is the Disposable that represents adding all of this object's menu items to Atom's own
* ContextMenuManager. When a new item is added to this object, we must remove all of the items
* that we previously added to the ContextMenuManager and then re-add them based on the new
* ordering of priorities that results from the new item.
*/
_disposable: ?IDisposable;
constructor(menuOptions: MenuOptions) {
constructor(menuOptions) {
this._menuOptions = menuOptions;

@@ -93,3 +45,11 @@ this._items = [];

*/
isEmpty(): boolean {
/**
* This is the Disposable that represents adding all of this object's menu items to Atom's own
* ContextMenuManager. When a new item is added to this object, we must remove all of the items
* that we previously added to the ContextMenuManager and then re-add them based on the new
* ordering of priorities that results from the new item.
*/
isEmpty() {
return this._items.length === 0;

@@ -106,4 +66,4 @@ }

*/
addItem(item: atom$ContextMenuItem, priority: number): IDisposable {
const value = {type: 'item', item, priority};
addItem(item, priority) {
const value = { type: 'item', item, priority };
return this._addItemToList(value);

@@ -120,8 +80,8 @@ }

*/
addSubmenu(contextMenu: ContextMenu, priority: number): IDisposable {
const value = {type: 'menu', menu: contextMenu, priority};
addSubmenu(contextMenu, priority) {
const value = { type: 'menu', menu: contextMenu, priority };
return this._addItemToList(value);
}
_addItemToList(value: InternalItem): IDisposable {
_addItemToList(value) {
this._items.push(value);

@@ -133,3 +93,3 @@ this._needsSort = true;

// disposed.
return new Disposable(() => {
return new _atom.Disposable(() => {
const index = this._items.indexOf(value);

@@ -149,3 +109,3 @@ this._items.splice(index, 1);

*/
_sort(): void {
_sort() {
if (!this._needsSort) {

@@ -165,6 +125,3 @@ return;

this._disposable = atom.contextMenu.add({
[menuOptions.cssSelector]: items.map(
this._contextMenuItemForInternalItem,
this,
),
[menuOptions.cssSelector]: items.map(this._contextMenuItemForInternalItem, this)
});

@@ -179,5 +136,3 @@ } else if (menuOptions.type === 'submenu') {

/** Translates this object's internal representation of a menu item to Atom's representation. */
_contextMenuItemForInternalItem(
internalItem: InternalItem,
): atom$ContextMenuItem {
_contextMenuItemForInternalItem(internalItem) {
if (internalItem.type === 'item') {

@@ -189,3 +144,7 @@ return internalItem.item;

const menuOptions = internalItem.menu._menuOptions;
invariant(menuOptions.type === 'submenu');
if (!(menuOptions.type === 'submenu')) {
throw new Error('Invariant violation: "menuOptions.type === \'submenu\'"');
}
const items = internalItem.menu._sortAndFilterItems();

@@ -195,11 +154,13 @@ return {

submenu: items.map(this._contextMenuItemForInternalItem, this),
shouldDisplay: menuOptions.shouldDisplay,
shouldDisplay: menuOptions.shouldDisplay
};
} else {
invariant(false);
if (!false) {
throw new Error('Invariant violation: "false"');
}
}
}
_sortAndFilterItems(): Array<InternalItem> {
const items = this._items.filter((item: InternalItem) => {
_sortAndFilterItems() {
const items = this._items.filter(item => {
if (item.type === 'item') {

@@ -225,16 +186,23 @@ return true;

static isEventFromContextMenu(event: Event) {
static isEventFromContextMenu(event) {
// Context menu commands contain a specific `detail` parameter:
// https://github.com/atom/atom/blob/v1.15.0/src/main-process/context-menu.coffee#L17
return (
Array.isArray(event.detail) &&
event.detail[0] &&
(event.detail[0]: any).contextCommand
);
return Array.isArray(event.detail) && event.detail[0] && event.detail[0].contextCommand;
}
}
/** Comparator used to sort menu items by priority: lower priorities appear earlier. */
function compareInternalItems(a: InternalItem, b: InternalItem): number {
exports.default = ContextMenu; /** Comparator used to sort menu items by priority: lower priorities appear earlier. */
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
*
* @format
*/
function compareInternalItems(a, b) {
return a.priority - b.priority;
}
}

@@ -1,14 +0,9 @@

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
* @flow
* @format
*/
'use strict';
import invariant from 'assert';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = createPackage;
/**

@@ -33,6 +28,3 @@ * Create an Atom package from an Activation constructor.

*/
export default function createPackage(
moduleExports: Object,
Activation: Class<any>,
): void {
function createPackage(moduleExports, Activation) {
let activation = null;

@@ -49,15 +41,13 @@

if (property === 'initialize') {
throw new Error(
'Your activation class contains an "initialize" method, but that work should be done in the' +
' constructor.',
);
throw new Error('Your activation class contains an "initialize" method, but that work should be done in the' + ' constructor.');
}
if (property === 'deactivate') {
throw new Error(
'Your activation class contains an "deactivate" method. Please use "dispose" instead.',
);
throw new Error('Your activation class contains an "deactivate" method. Please use "dispose" instead.');
}
moduleExports[property] = function(...args) {
invariant(activation != null, 'Package not initialized');
moduleExports[property] = function (...args) {
if (!(activation != null)) {
throw new Error('Package not initialized');
}
return activation[property](...args);

@@ -70,4 +60,7 @@ };

*/
moduleExports.initialize = (initialState: ?Object): void => {
invariant(activation == null, 'Package already initialized');
moduleExports.initialize = initialState => {
if (!(activation == null)) {
throw new Error('Package already initialized');
}
activation = new Activation(initialState);

@@ -79,4 +72,7 @@ };

*/
moduleExports.deactivate = (): void => {
invariant(activation != null, 'Package not initialized');
moduleExports.deactivate = () => {
if (!(activation != null)) {
throw new Error('Package not initialized');
}
if (typeof activation.dispose === 'function') {

@@ -87,5 +83,14 @@ activation.dispose();

};
}
} /**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
*
* @format
*/
function getPrototypeChain(prototype: Class<any>): Array<Class<any>> {
function getPrototypeChain(prototype) {
let currentPrototype = prototype;

@@ -104,6 +109,6 @@ const prototypes = [];

*/
function getPropertyList(prototype: Class<any>): Array<string> {
function getPropertyList(prototype) {
const properties = [];
for (const proto of getPrototypeChain(prototype)) {
if (proto === (Object: any).prototype) {
if (proto === Object.prototype) {
break;

@@ -116,2 +121,2 @@ }

return properties;
}
}

@@ -1,12 +0,37 @@

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
* @flow
* @format
*/
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.observeActivePaneItemDebounced = observeActivePaneItemDebounced;
exports.observeActiveEditorsDebounced = observeActiveEditorsDebounced;
exports.editorChangesDebounced = editorChangesDebounced;
exports.editorScrollTopDebounced = editorScrollTopDebounced;
exports.observeTextEditorsPositions = observeTextEditorsPositions;
var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js');
var _event;
function _load_event() {
return _event = require('nuclide-commons/event');
}
var _textEditor;
function _load_textEditor() {
return _textEditor = require('./text-editor');
}
const DEFAULT_PANE_DEBOUNCE_INTERVAL_MS = 100; /**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
*
* @format
*/
/**

@@ -21,16 +46,7 @@ * Often, we may want to respond to Atom events, but only after a buffer period

import {Observable} from 'rxjs';
import {observableFromSubscribeFunction} from 'nuclide-commons/event';
import {getCursorPositions, isValidTextEditor} from './text-editor';
import invariant from 'assert';
const DEFAULT_PANE_DEBOUNCE_INTERVAL_MS = 100;
const DEFAULT_EDITOR_DEBOUNCE_INTERVAL_MS = 300;
const DEFAULT_POSITION_DEBOUNCE_INTERVAL_MS = 300;
export function observeActivePaneItemDebounced(
debounceInterval: number = DEFAULT_PANE_DEBOUNCE_INTERVAL_MS,
): Observable<mixed> {
return observableFromSubscribeFunction(callback => {
function observeActivePaneItemDebounced(debounceInterval = DEFAULT_PANE_DEBOUNCE_INTERVAL_MS) {
return (0, (_event || _load_event()).observableFromSubscribeFunction)(callback => {
if (atom.workspace.getCenter != null) {

@@ -43,10 +59,8 @@ return atom.workspace.getCenter().observeActivePaneItem(callback);

export function observeActiveEditorsDebounced(
debounceInterval: number = DEFAULT_PANE_DEBOUNCE_INTERVAL_MS,
): Observable<?atom$TextEditor> {
function observeActiveEditorsDebounced(debounceInterval = DEFAULT_PANE_DEBOUNCE_INTERVAL_MS) {
return observeActivePaneItemDebounced(debounceInterval).map(paneItem => {
if (isValidTextEditor(paneItem)) {
if ((0, (_textEditor || _load_textEditor()).isValidTextEditor)(paneItem)) {
// Flow cannot understand the type refinement provided by the isValidTextEditor function,
// so we have to cast.
return ((paneItem: any): atom$TextEditor);
return paneItem;
}

@@ -57,46 +71,25 @@ return null;

export function editorChangesDebounced(
editor: atom$TextEditor,
debounceInterval: number = DEFAULT_EDITOR_DEBOUNCE_INTERVAL_MS,
): Observable<void> {
return (
observableFromSubscribeFunction(callback => editor.onDidChange(callback))
// Debounce manually rather than using editor.onDidStopChanging so that the debounce time is
// configurable.
.debounceTime(debounceInterval)
);
function editorChangesDebounced(editor, debounceInterval = DEFAULT_EDITOR_DEBOUNCE_INTERVAL_MS) {
return (0, (_event || _load_event()).observableFromSubscribeFunction)(callback => editor.onDidChange(callback))
// Debounce manually rather than using editor.onDidStopChanging so that the debounce time is
// configurable.
.debounceTime(debounceInterval);
}
export function editorScrollTopDebounced(
editor: atom$TextEditor,
debounceInterval: number = DEFAULT_EDITOR_DEBOUNCE_INTERVAL_MS,
): Observable<number> {
return observableFromSubscribeFunction(callback =>
atom.views.getView(editor).onDidChangeScrollTop(callback),
).debounceTime(debounceInterval);
function editorScrollTopDebounced(editor, debounceInterval = DEFAULT_EDITOR_DEBOUNCE_INTERVAL_MS) {
return (0, (_event || _load_event()).observableFromSubscribeFunction)(callback => atom.views.getView(editor).onDidChangeScrollTop(callback)).debounceTime(debounceInterval);
}
export type EditorPosition = {
editor: atom$TextEditor,
position: atom$Point,
};
// Yields null when the current pane is not an editor,
// otherwise yields events on each move of the primary cursor within any Editor.
export function observeTextEditorsPositions(
editorDebounceInterval: number = DEFAULT_EDITOR_DEBOUNCE_INTERVAL_MS,
positionDebounceInterval: number = DEFAULT_POSITION_DEBOUNCE_INTERVAL_MS,
): Observable<?EditorPosition> {
return observeActiveEditorsDebounced(
editorDebounceInterval,
).switchMap(editor => {
return editor == null
? Observable.of(null)
: getCursorPositions(editor)
.debounceTime(positionDebounceInterval)
.map(position => {
invariant(editor != null);
return {editor, position};
});
function observeTextEditorsPositions(editorDebounceInterval = DEFAULT_EDITOR_DEBOUNCE_INTERVAL_MS, positionDebounceInterval = DEFAULT_POSITION_DEBOUNCE_INTERVAL_MS) {
return observeActiveEditorsDebounced(editorDebounceInterval).switchMap(editor => {
return editor == null ? _rxjsBundlesRxMinJs.Observable.of(null) : (0, (_textEditor || _load_textEditor()).getCursorPositions)(editor).debounceTime(positionDebounceInterval).map(position => {
if (!(editor != null)) {
throw new Error('Invariant violation: "editor != null"');
}
return { editor, position };
});
});
}
}

@@ -0,1 +1,10 @@

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js');
// Default to "nuclide", but only for unit tests.
/**

@@ -8,3 +17,3 @@ * Copyright (c) 2015-present, Facebook, Inc.

*
* @flow
*
* @format

@@ -18,6 +27,2 @@ */

import invariant from 'assert';
import {Observable} from 'rxjs';
// Default to "nuclide", but only for unit tests.
let packageName = atom.inSpecMode() ? 'nuclide' : null;

@@ -29,8 +34,11 @@

*/
function setPackageName(name: string): void {
function setPackageName(name) {
packageName = name;
}
function formatKeyPath(keyPath: string): string {
invariant(packageName, 'feature-config must be used with FeatureLoader.');
function formatKeyPath(keyPath) {
if (!packageName) {
throw new Error('feature-config must be used with FeatureLoader.');
}
return `${packageName}.${keyPath}`;

@@ -51,28 +59,10 @@ }

*/
function get(
keyPath: string,
options?: {
excludeSources?: Array<string>,
sources?: Array<string>,
scope?: Object,
},
): mixed {
function get(keyPath, options) {
// atom.config.get will crash if the second arg is present and undefined.
// It does not crash if the second arg is missing.
return atom.config.get(
formatKeyPath(keyPath),
...(options == null ? [] : [options]),
);
return atom.config.get(formatKeyPath(keyPath), ...(options == null ? [] : [options]));
}
function getWithDefaults<T>(
keyPath: string,
defaults: T,
options?: {
excludeSources?: Array<string>,
sources?: Array<string>,
scope?: Object,
},
): T {
const current: any = get(keyPath, options);
function getWithDefaults(keyPath, defaults, options) {
const current = get(keyPath, options);
return current == null ? defaults : current;

@@ -85,3 +75,3 @@ }

*/
function getSchema(keyPath: string): atom$ConfigSchema {
function getSchema(keyPath) {
return atom.config.getSchema(formatKeyPath(keyPath));

@@ -95,6 +85,3 @@ }

*/
function observe(
keyPath: string,
callback: (value: mixed) => mixed,
): IDisposable {
function observe(keyPath, callback) {
return atom.config.observe(formatKeyPath(keyPath), callback);

@@ -107,4 +94,4 @@ }

*/
function observeAsStream(keyPath: string): Observable<mixed> {
return Observable.create(observer => {
function observeAsStream(keyPath) {
return _rxjsBundlesRxMinJs.Observable.create(observer => {
const disposable = observe(keyPath, observer.next.bind(observer));

@@ -119,11 +106,4 @@ return disposable.dispose.bind(disposable);

*/
function onDidChange(
keyPath: string,
optionsOrCallback: Object | ((event: Object) => void),
callback?: (event: Object) => void,
): IDisposable {
return atom.config.onDidChange(
formatKeyPath(keyPath),
...Array.prototype.slice.call(arguments, 1),
);
function onDidChange(keyPath, optionsOrCallback, callback) {
return atom.config.onDidChange(formatKeyPath(keyPath), ...Array.prototype.slice.call(arguments, 1));
}

@@ -135,14 +115,4 @@

*/
function set(
keyPath: string,
value: ?mixed,
options?: {
scopeSelector?: string,
source?: string,
},
): boolean {
return atom.config.set(
formatKeyPath(keyPath),
...Array.prototype.slice.call(arguments, 1),
);
function set(keyPath, value, options) {
return atom.config.set(formatKeyPath(keyPath), ...Array.prototype.slice.call(arguments, 1));
}

@@ -154,7 +124,4 @@

*/
function setSchema(keyPath: string, schema: Object): void {
return atom.config.setSchema(
formatKeyPath(keyPath),
...Array.prototype.slice.call(arguments, 1),
);
function setSchema(keyPath, schema) {
return atom.config.setSchema(formatKeyPath(keyPath), ...Array.prototype.slice.call(arguments, 1));
}

@@ -166,13 +133,4 @@

*/
function unset(
keyPath: string,
options?: {
scopeSelector?: string,
source?: string,
},
): void {
return atom.config.unset(
formatKeyPath(keyPath),
...Array.prototype.slice.call(arguments, 1),
);
function unset(keyPath, options) {
return atom.config.unset(formatKeyPath(keyPath), ...Array.prototype.slice.call(arguments, 1));
}

@@ -184,11 +142,11 @@

*/
function isFeatureDisabled(name: string): boolean {
invariant(packageName, 'feature-config must be used with FeatureLoader.');
return (
atom.packages.isPackageDisabled(packageName) ||
!atom.config.get(`${packageName}.use.${name}`)
);
function isFeatureDisabled(name) {
if (!packageName) {
throw new Error('feature-config must be used with FeatureLoader.');
}
return atom.packages.isPackageDisabled(packageName) || !atom.config.get(`${packageName}.use.${name}`);
}
export default {
exports.default = {
setPackageName,

@@ -204,3 +162,3 @@ get,

unset,
isFeatureDisabled,
};
isFeatureDisabled
};

@@ -1,50 +0,26 @@

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
* @flow
* @format
*/
'use strict';
/* global localStorage */
Object.defineProperty(exports, "__esModule", {
value: true
});
import invariant from 'assert';
import UniversalDisposable from 'nuclide-commons/UniversalDisposable';
import featureConfig from './feature-config';
var _UniversalDisposable;
type FeaturePkg = {
atomConfig?: Object,
consumedServices?: Object,
description?: string,
name: string,
nuclide?: {
config?: Object,
},
providedServices?: Object,
};
function _load_UniversalDisposable() {
return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable'));
}
export type Feature = {
dirname: string,
pkg: FeaturePkg,
};
var _featureConfig;
type FeatureLoaderParams = {
pkgName: string,
features: Array<Feature>,
};
function _load_featureConfig() {
return _featureConfig = _interopRequireDefault(require('./feature-config'));
}
export default class FeatureLoader {
_activationDisposable: ?UniversalDisposable;
_loadDisposable: UniversalDisposable;
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
_config: Object;
_features: Array<Feature>;
_pkgName: string;
class FeatureLoader {
constructor({config, features, pkgName}: FeatureLoaderParams) {
constructor({ config, features, pkgName }) {
this._features = features;
this._loadDisposable = new UniversalDisposable();
this._loadDisposable = new (_UniversalDisposable || _load_UniversalDisposable()).default();
this._pkgName = pkgName;

@@ -55,4 +31,4 @@ this._config = {

collapsed: true,
properties: {},
},
properties: {}
}
};

@@ -62,4 +38,6 @@ }

// Build the config. Should occur with root package's load
load(): void {
invariant(!this._loadDisposable.disposed);
load() {
if (!!this._loadDisposable.disposed) {
throw new Error('Invariant violation: "!this._loadDisposable.disposed"');
}

@@ -76,9 +54,9 @@ // Add a dummy deserializer. This forces Atom to load Nuclide's main module

// [1] https://github.com/atom/atom/blob/v1.9.8/src/package.coffee#L442
this._loadDisposable.add(
atom.deserializers.add({
name: `${this._pkgName}.ForceMainModuleLoad`,
deserialize() {},
}),
);
this._loadDisposable.add(atom.deserializers.add({
name: `${this._pkgName}.ForceMainModuleLoad`,
deserialize() {}
}));
//

@@ -105,3 +83,3 @@ // Build the "config" object. This determines the config defaults and

type: 'boolean',
default: enabled,
default: enabled
};

@@ -119,5 +97,3 @@ if (featurePkg.providedServices) {

// Merge in the feature's config
const featurePkgConfig =
featurePkg.atomConfig ||
(featurePkg.nuclide && featurePkg.nuclide.config);
const featurePkgConfig = featurePkg.atomConfig || featurePkg.nuclide && featurePkg.nuclide.config;

@@ -128,13 +104,12 @@ if (featurePkgConfig) {

collapsed: true,
properties: {},
properties: {}
};
Object.keys(featurePkgConfig).forEach(key => {
this._config[name].properties[key] = {
...featurePkgConfig[key],
title: featurePkgConfig[key].title || key,
};
this._config[name].properties[key] = Object.assign({}, featurePkgConfig[key], {
title: featurePkgConfig[key].title || key
});
});
}
});
featureConfig.setPackageName(this._pkgName);
(_featureConfig || _load_featureConfig()).default.setPackageName(this._pkgName);

@@ -159,5 +134,3 @@ // Nesting loads within loads leads to reverse activation order- that is, if

const enabled = atom.config.get(this.useKeyPathForFeature(feature));
const shouldEnable = enabled == null
? this._config.use.properties[feature.pkg.name].default
: enabled;
const shouldEnable = enabled == null ? this._config.use.properties[feature.pkg.name].default : enabled;

@@ -169,3 +142,6 @@ if (shouldEnable) {

invariant(initialLoadDisposable != null);
if (!(initialLoadDisposable != null)) {
throw new Error('Invariant violation: "initialLoadDisposable != null"');
}
this._loadDisposable.remove(initialLoadDisposable);

@@ -178,15 +154,20 @@ initialLoadDisposable.dispose();

activate(): void {
invariant(this._activationDisposable == null);
activate() {
if (!(this._activationDisposable == null)) {
throw new Error('Invariant violation: "this._activationDisposable == null"');
}
const rootPackage = atom.packages.getLoadedPackage(this._pkgName);
invariant(rootPackage != null);
if (!(rootPackage != null)) {
throw new Error('Invariant violation: "rootPackage != null"');
}
// This is a failsafe in case the `.ForceMainModuleLoad` deserializer
// defined above does not register in time, or if the defer key has been set
// w/o our knowledge. This can happen during OSS upgrades.
localStorage.removeItem(
rootPackage.getCanDeferMainModuleRequireStorageKey(),
);
localStorage.removeItem(rootPackage.getCanDeferMainModuleRequireStorageKey());
this._features.forEach(feature => {

@@ -199,19 +180,15 @@ if (atom.config.get(this.useKeyPathForFeature(feature))) {

// Watch the config to manage toggling features
this._activationDisposable = new UniversalDisposable(
...this._features.map(feature =>
atom.config.onDidChange(this.useKeyPathForFeature(feature), event => {
if (event.newValue === true) {
atom.packages.activatePackage(feature.dirname);
} else if (event.newValue === false) {
safeDeactivate(feature);
}
}),
),
);
this._activationDisposable = new (_UniversalDisposable || _load_UniversalDisposable()).default(...this._features.map(feature => atom.config.onDidChange(this.useKeyPathForFeature(feature), event => {
if (event.newValue === true) {
atom.packages.activatePackage(feature.dirname);
} else if (event.newValue === false) {
safeDeactivate(feature);
}
})));
}
deactivate(): void {
invariant(
this._activationDisposable && !this._activationDisposable.disposed,
);
deactivate() {
if (!(this._activationDisposable && !this._activationDisposable.disposed)) {
throw new Error('Invariant violation: "this._activationDisposable && !this._activationDisposable.disposed"');
}

@@ -224,3 +201,7 @@ this._features.forEach(feature => {

invariant(this._activationDisposable); // reasserting for flow
if (!this._activationDisposable) {
throw new Error('Invariant violation: "this._activationDisposable"');
} // reasserting for flow
this._activationDisposable.dispose();

@@ -230,7 +211,7 @@ this._activationDisposable = null;

getConfig(): Object {
getConfig() {
return this._config;
}
serialize(): void {
serialize() {
// When the root package is serialized, all of its features need to be serialized. This is an abuse of

@@ -244,3 +225,3 @@ // `serialize()` since we're using it to do side effects instead of returning the serialization,

useKeyPathForFeature(feature: Feature): string {
useKeyPathForFeature(feature) {
return `${this._pkgName}.use.${feature.pkg.name}`;

@@ -250,6 +231,16 @@ }

function safeDeactivate(
feature: Feature,
suppressSerialization: boolean = false,
) {
exports.default = FeatureLoader; /**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
*
* @format
*/
/* global localStorage */
function safeDeactivate(feature, suppressSerialization = false) {
const name = feature.pkg.name;

@@ -267,3 +258,3 @@ try {

function safeSerialize(feature: Feature) {
function safeSerialize(feature) {
const name = feature.pkg.name;

@@ -280,2 +271,2 @@ try {

}
}
}

@@ -1,16 +0,10 @@

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
* @flow
* @format
*/
'use strict';
import {Subject} from 'rxjs';
import type {Observable} from 'rxjs';
import invariant from 'assert';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.goToLocation = undefined;
var _asyncToGenerator = _interopRequireDefault(require('async-to-generator'));
/**

@@ -40,52 +34,61 @@ * Opens the given file.

*/
export async function goToLocation(
file: string,
line?: number,
column?: number,
center?: boolean = true,
): Promise<atom$TextEditor> {
// Prefer going to the current editor rather than the leftmost editor.
const currentEditor = atom.workspace.getActiveTextEditor();
if (currentEditor != null && currentEditor.getPath() === file) {
if (line != null) {
goToLocationInEditor(
currentEditor,
line,
column == null ? 0 : column,
center,
);
let goToLocation = exports.goToLocation = (() => {
var _ref = (0, _asyncToGenerator.default)(function* (file, line, column, center = true) {
// Prefer going to the current editor rather than the leftmost editor.
const currentEditor = atom.workspace.getActiveTextEditor();
if (currentEditor != null && currentEditor.getPath() === file) {
if (line != null) {
goToLocationInEditor(currentEditor, line, column == null ? 0 : column, center);
} else {
if (!(column == null)) {
throw new Error('goToLocation: Cannot specify just column');
}
}
return currentEditor;
} else {
invariant(column == null, 'goToLocation: Cannot specify just column');
}
return currentEditor;
} else {
// Obviously, calling goToLocation isn't a viable alternative here :P
// eslint-disable-next-line nuclide-internal/atom-apis
const editor = await atom.workspace.open(file, {
initialLine: line,
initialColumn: column,
searchAllPanes: true,
});
// Obviously, calling goToLocation isn't a viable alternative here :P
// eslint-disable-next-line nuclide-internal/atom-apis
const editor = yield atom.workspace.open(file, {
initialLine: line,
initialColumn: column,
searchAllPanes: true
});
if (center && line != null) {
editor.scrollToBufferPosition([line, column], {center: true});
if (center && line != null) {
editor.scrollToBufferPosition([line, column], { center: true });
}
return editor;
}
return editor;
}
}
});
const goToLocationSubject = new Subject();
return function goToLocation(_x, _x2, _x3) {
return _ref.apply(this, arguments);
};
})(); /**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
*
* @format
*/
exports.goToLocationInEditor = goToLocationInEditor;
exports.observeNavigatingEditors = observeNavigatingEditors;
var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const goToLocationSubject = new _rxjsBundlesRxMinJs.Subject();
// Scrolls to the given line/column at the given editor
// broadcasts the editor instance on an observable (subject) available
// through the getGoToLocation
export function goToLocationInEditor(
editor: atom$TextEditor,
line: number,
column: number,
center: boolean = true,
): void {
function goToLocationInEditor(editor, line, column, center = true) {
editor.setCursorBufferPosition([line, column]);
if (center) {
editor.scrollToBufferPosition([line, column], {center: true});
editor.scrollToBufferPosition([line, column], { center: true });
}

@@ -96,4 +99,4 @@

export function observeNavigatingEditors(): Observable<atom$TextEditor> {
function observeNavigatingEditors() {
return goToLocationSubject;
}
}

@@ -1,26 +0,34 @@

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
* @flow
* @format
*/
'use strict';
import invariant from 'assert';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.bufferPositionForMouseEvent = bufferPositionForMouseEvent;
function bufferPositionForMouseEvent(event, editor = null) {
const _editor = editor || atom.workspace.getActiveTextEditor();
export function bufferPositionForMouseEvent(
event: MouseEvent,
editor: ?atom$TextEditor = null,
): atom$Point {
const _editor = editor || atom.workspace.getActiveTextEditor();
invariant(_editor != null);
if (!(_editor != null)) {
throw new Error('Invariant violation: "_editor != null"');
}
const view = atom.views.getView(_editor);
const component = view.component;
invariant(component != null);
if (!(component != null)) {
throw new Error('Invariant violation: "component != null"');
}
// Beware, screenPositionForMouseEvent is not a public api and may change in future versions.
const screenPosition = component.screenPositionForMouseEvent(event);
return _editor.bufferPositionForScreenPosition(screenPosition);
}
} /**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
*
* @format
*/

@@ -1,21 +0,27 @@

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
* @flow
* @format
*/
'use strict';
import {observableFromSubscribeFunction} from 'nuclide-commons/event';
import memoizeUntilChanged from 'nuclide-commons/memoizeUntilChanged';
import {Observable, Scheduler} from 'rxjs';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = observePaneItemVisibility;
var _event;
function _load_event() {
return _event = require('nuclide-commons/event');
}
var _memoizeUntilChanged;
function _load_memoizeUntilChanged() {
return _memoizeUntilChanged = _interopRequireDefault(require('nuclide-commons/memoizeUntilChanged'));
}
var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// TODO(T17495608): Currently, docks don't have a way of observing their visibility so this will
// have some false positives when an item is its pane's active item but its dock is hidden.
export default function observePaneItemVisibility(
item: Object,
): Observable<boolean> {
function observePaneItemVisibility(item) {
// If this is a version of Atom that doesn't have Docks, return an empty observable. Until they

@@ -26,3 +32,3 @@ // land, the functionality is provided by the workspace views package, which calls

if (atom.workspace.getPaneContainers == null) {
return Observable.empty();
return _rxjsBundlesRxMinJs.Observable.empty();
}

@@ -33,31 +39,30 @@

// $FlowFixMe: Add atom.workspace.getElement() after 1.17.
return observeActiveItems(atom.workspace.getElement())
.map(activeItems => activeItems.includes(item))
.distinctUntilChanged();
}
return observeActiveItems(atom.workspace.getElement()).map(activeItems => activeItems.includes(item)).distinctUntilChanged();
} /**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
*
* @format
*/
const observeActiveItems = memoizeUntilChanged(_cacheKey => {
const observeActiveItems = (0, (_memoizeUntilChanged || _load_memoizeUntilChanged()).default)(_cacheKey => {
// An observable that emits `{pane, item}` whenever the active item of a pane changes.
const itemActivations = Observable.merge(
// $FlowFixMe: Add `getPaneContainers()` to the type defs once Atom 1.17 lands.
...atom.workspace.getPaneContainers().map(paneContainer => {
const observePanes = paneContainer.observePanes.bind(paneContainer);
return observableFromSubscribeFunction(observePanes).flatMap(pane => {
const paneDestroyed = observableFromSubscribeFunction(
pane.onDidDestroy.bind(pane),
);
const activeItems = observableFromSubscribeFunction(
pane.observeActiveItem.bind(pane),
).takeUntil(paneDestroyed);
return Observable.concat(
activeItems.map(item => ({pane, item})),
Observable.of({pane, item: null}),
);
});
}),
);
const itemActivations = _rxjsBundlesRxMinJs.Observable.merge(
// $FlowFixMe: Add `getPaneContainers()` to the type defs once Atom 1.17 lands.
...atom.workspace.getPaneContainers().map(paneContainer => {
const observePanes = paneContainer.observePanes.bind(paneContainer);
return (0, (_event || _load_event()).observableFromSubscribeFunction)(observePanes).flatMap(pane => {
const paneDestroyed = (0, (_event || _load_event()).observableFromSubscribeFunction)(pane.onDidDestroy.bind(pane));
const activeItems = (0, (_event || _load_event()).observableFromSubscribeFunction)(pane.observeActiveItem.bind(pane)).takeUntil(paneDestroyed);
return _rxjsBundlesRxMinJs.Observable.concat(activeItems.map(item => ({ pane, item })), _rxjsBundlesRxMinJs.Observable.of({ pane, item: null }));
});
}));
// Create a map of panes to their active items. We could look this up by examining the workspace
// every time; this is an optimization.
const panesToActiveItem = itemActivations.scan((acc, {pane, item}) => {
const panesToActiveItem = itemActivations.scan((acc, { pane, item }) => {
if (item == null) {

@@ -71,10 +76,6 @@ acc.delete(pane);

return (
panesToActiveItem
// When dragging items between panes, they'll be quickly deactivated and activated again. To
// avoid doing extra work, we debounce and use the rAF scheduler.
.debounceTime(0, Scheduler.animationFrame)
.map(map => Array.from(map.values()))
.share()
);
});
return panesToActiveItem
// When dragging items between panes, they'll be quickly deactivated and activated again. To
// avoid doing extra work, we debounce and use the rAF scheduler.
.debounceTime(0, _rxjsBundlesRxMinJs.Scheduler.animationFrame).map(map => Array.from(map.values())).share();
});
{
"name": "nuclide-commons-atom",
"version": "0.1.3",
"version": "0.1.4",
"description": "Common Nuclide node modules (for use with Atom only).",

@@ -9,3 +9,3 @@ "license": "SEE LICENSE IN LICENSE",

"scripts": {
"prepublishOnly": "../../scripts/release-transpile.js --overwrite .",
"prepublish": "../../scripts/modules-prepublish.sh",
"test": "atom --dev --test spec"

@@ -17,3 +17,3 @@ },

"log4js": "1.1.1",
"nuclide-commons": "0.1.3",
"nuclide-commons": "0.1.4",
"rxjs": "5.3.1",

@@ -20,0 +20,0 @@ "semver": "5.3.0"

@@ -1,35 +0,46 @@

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
* @flow
* @format
*/
'use strict';
import type {NuclideUri} from 'nuclide-commons/nuclideUri';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getAtomProjectRelativePath = getAtomProjectRelativePath;
exports.getAtomProjectRootPath = getAtomProjectRootPath;
exports.relativizePathWithDirectory = relativizePathWithDirectory;
exports.getDirectoryForPath = getDirectoryForPath;
exports.getFileForPath = getFileForPath;
exports.observeProjectPaths = observeProjectPaths;
exports.onDidAddProjectPath = onDidAddProjectPath;
exports.onDidRemoveProjectPath = onDidRemoveProjectPath;
import {File, Directory} from 'atom';
import nuclideUri from 'nuclide-commons/nuclideUri';
var _atom = require('atom');
function getValidProjectPaths(): Array<string> {
return atom.project
.getDirectories()
.filter(directory => {
// If a remote directory path is a local `Directory` instance, the project path
// isn't yet ready for consumption.
if (
nuclideUri.isRemote(directory.getPath()) &&
directory instanceof Directory
) {
return false;
}
return true;
})
.map(directory => directory.getPath());
var _nuclideUri;
function _load_nuclideUri() {
return _nuclideUri = _interopRequireDefault(require('nuclide-commons/nuclideUri'));
}
export function getAtomProjectRelativePath(path: NuclideUri): ?string {
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function getValidProjectPaths() {
return atom.project.getDirectories().filter(directory => {
// If a remote directory path is a local `Directory` instance, the project path
// isn't yet ready for consumption.
if ((_nuclideUri || _load_nuclideUri()).default.isRemote(directory.getPath()) && directory instanceof _atom.Directory) {
return false;
}
return true;
}).map(directory => directory.getPath());
} /**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
*
* @format
*/
function getAtomProjectRelativePath(path) {
const [projectPath, relativePath] = atom.project.relativizePath(path);

@@ -42,3 +53,3 @@ if (!projectPath) {

export function getAtomProjectRootPath(path: NuclideUri): ?string {
function getAtomProjectRootPath(path) {
const [projectPath] = atom.project.relativizePath(path);

@@ -55,8 +66,6 @@ return projectPath;

*/
export function relativizePathWithDirectory(
path: NuclideUri,
): [?Directory, NuclideUri] {
function relativizePathWithDirectory(path) {
for (const directory of atom.project.getDirectories()) {
try {
const relativePath = nuclideUri.relative(directory.getPath(), path);
const relativePath = (_nuclideUri || _load_nuclideUri()).default.relative(directory.getPath(), path);
return [directory, relativePath];

@@ -70,3 +79,3 @@ } catch (e) {

export function getDirectoryForPath(path: NuclideUri): ?Directory {
function getDirectoryForPath(path) {
const [directory, relativePath] = relativizePathWithDirectory(path);

@@ -79,3 +88,3 @@ if (directory == null) {

export function getFileForPath(path: NuclideUri): ?File {
function getFileForPath(path) {
const [directory, relativePath] = relativizePathWithDirectory(path);

@@ -88,5 +97,3 @@ if (directory == null) {

export function observeProjectPaths(
callback: (projectPath: string) => any,
): IDisposable {
function observeProjectPaths(callback) {
getValidProjectPaths().forEach(callback);

@@ -96,7 +103,5 @@ return onDidAddProjectPath(callback);

export function onDidAddProjectPath(
callback: (projectPath: string) => void,
): IDisposable {
let projectPaths: Array<string> = getValidProjectPaths();
let changing: boolean = false;
function onDidAddProjectPath(callback) {
let projectPaths = getValidProjectPaths();
let changing = false;
return atom.project.onDidChangePaths(() => {

@@ -118,7 +123,5 @@ if (changing) {

export function onDidRemoveProjectPath(
callback: (projectPath: string) => void,
): IDisposable {
let projectPaths: Array<string> = getValidProjectPaths();
let changing: boolean = false;
function onDidRemoveProjectPath(callback) {
let projectPaths = getValidProjectPaths();
let changing = false;
return atom.project.onDidChangePaths(() => {

@@ -138,2 +141,2 @@ if (changing) {

});
}
}

@@ -1,20 +0,8 @@

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
* @flow
* @format
*/
"use strict";
export type Provider = {
priority: number,
grammarScopes: Array<string>,
};
Object.defineProperty(exports, "__esModule", {
value: true
});
class ProviderRegistry {
export default class ProviderRegistry<T: Provider> {
_providers: Set<T>;
constructor() {

@@ -24,11 +12,11 @@ this._providers = new Set();

addProvider(provider: T): void {
addProvider(provider) {
this._providers.add(provider);
}
removeProvider(provider: T): void {
removeProvider(provider) {
this._providers.delete(provider);
}
getProviderForEditor(editor: atom$TextEditor): ?T {
getProviderForEditor(editor) {
const grammar = editor.getGrammar().scopeName;

@@ -38,3 +26,3 @@ return this.findProvider(grammar);

findProvider(grammar: string): ?T {
findProvider(grammar) {
let bestProvider = null;

@@ -53,1 +41,11 @@ let bestPriority = Number.NEGATIVE_INFINITY;

}
exports.default = ProviderRegistry; /**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
*
* @format
*/

@@ -0,1 +1,17 @@

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.wordAtPosition = wordAtPosition;
exports.trimRange = trimRange;
var _atom = require('atom');
var _range;
function _load_range() {
return _range = require('nuclide-commons/range');
}
/**

@@ -8,14 +24,7 @@ * Copyright (c) 2015-present, Facebook, Inc.

*
* @flow
*
* @format
*/
import {Range} from 'atom';
import {wordAtPositionFromBuffer} from 'nuclide-commons/range';
export function wordAtPosition(
editor: atom$TextEditor,
position: atom$PointObject,
wordRegex_: ?RegExp,
): ?{wordMatch: Array<string>, range: atom$Range} {
function wordAtPosition(editor, position, wordRegex_) {
let wordRegex = wordRegex_;

@@ -26,3 +35,3 @@ if (!wordRegex) {

const buffer = editor.getBuffer();
return wordAtPositionFromBuffer(buffer, position, wordRegex);
return (0, (_range || _load_range()).wordAtPositionFromBuffer)(buffer, position, wordRegex);
}

@@ -41,18 +50,14 @@

*/
export function trimRange(
editor: atom$TextEditor,
rangeToTrim: atom$Range,
stopRegex: RegExp = /\S/,
): atom$Range {
function trimRange(editor, rangeToTrim, stopRegex = /\S/) {
const buffer = editor.getBuffer();
let {start, end} = rangeToTrim;
buffer.scanInRange(stopRegex, rangeToTrim, ({range, stop}) => {
let { start, end } = rangeToTrim;
buffer.scanInRange(stopRegex, rangeToTrim, ({ range, stop }) => {
start = range.start;
stop();
});
buffer.backwardsScanInRange(stopRegex, rangeToTrim, ({range, stop}) => {
buffer.backwardsScanInRange(stopRegex, rangeToTrim, ({ range, stop }) => {
end = range.end;
stop();
});
return new Range(start, end);
}
return new _atom.Range(start, end);
}

@@ -1,17 +0,1 @@

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
* @flow
* @format
*/
export type TextEdit = {
oldRange: atom$Range,
newText: string,
// If included, this will be used to verify that the edit still applies cleanly.
oldText?: string,
};
"use strict";

@@ -1,18 +0,14 @@

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
* @flow
* @format
*/
'use strict';
import type {NuclideUri} from 'nuclide-commons/nuclideUri';
import type {TextEdit} from './text-edit-rpc-types';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.applyTextEdits = applyTextEdits;
exports.applyTextEditsToBuffer = applyTextEditsToBuffer;
import invariant from 'assert';
var _textEditor;
import {existingEditorForUri} from './text-editor';
function _load_textEditor() {
return _textEditor = require('./text-editor');
}

@@ -31,15 +27,24 @@ /**

*/
export function applyTextEdits(
path: NuclideUri,
...edits: Array<TextEdit>
): boolean {
const editor = existingEditorForUri(path);
invariant(editor != null);
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
*
* @format
*/
function applyTextEdits(path, ...edits) {
const editor = (0, (_textEditor || _load_textEditor()).existingEditorForUri)(path);
if (!(editor != null)) {
throw new Error('Invariant violation: "editor != null"');
}
return applyTextEditsToBuffer(editor.getBuffer(), edits);
}
export function applyTextEditsToBuffer(
buffer: atom$TextBuffer,
edits: Array<TextEdit>,
): boolean {
function applyTextEditsToBuffer(buffer, edits) {
// Special-case whole-buffer changes to minimize disruption.

@@ -71,3 +76,3 @@ if (edits.length === 1 && edits[0].oldRange.isEqual(buffer.getRange())) {

function applyToBuffer(buffer: atom$TextBuffer, edit: TextEdit): boolean {
function applyToBuffer(buffer, edit) {
if (edit.oldRange.start.row === edit.oldRange.end.row) {

@@ -90,2 +95,2 @@ // A little extra validation when the old range spans only one line. In particular, this helps

return true;
}
}

@@ -1,20 +0,36 @@

/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
* @flow
* @format
*/
'use strict';
import type {NuclideUri} from 'nuclide-commons/nuclideUri';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.existingEditorForUri = existingEditorForUri;
exports.existingEditorForBuffer = existingEditorForBuffer;
exports.getViewOfEditor = getViewOfEditor;
exports.getScrollTop = getScrollTop;
exports.setScrollTop = setScrollTop;
exports.setPositionAndScroll = setPositionAndScroll;
exports.getCursorPositions = getCursorPositions;
exports.observeEditorDestroy = observeEditorDestroy;
exports.enforceReadOnly = enforceReadOnly;
exports.enforceSoftWrap = enforceSoftWrap;
exports.observeTextEditors = observeTextEditors;
exports.isValidTextEditor = isValidTextEditor;
exports.centerScrollToBufferLine = centerScrollToBufferLine;
import invariant from 'assert';
import {Observable} from 'rxjs';
var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js');
import {observableFromSubscribeFunction} from 'nuclide-commons/event';
import nuclideUri from 'nuclide-commons/nuclideUri';
var _event;
function _load_event() {
return _event = require('nuclide-commons/event');
}
var _nuclideUri;
function _load_nuclideUri() {
return _nuclideUri = _interopRequireDefault(require('nuclide-commons/nuclideUri'));
}
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**

@@ -24,3 +40,3 @@ * Returns a text editor that has the given path open, or null if none exists. If there are multiple

*/
export function existingEditorForUri(path: NuclideUri): ?atom$TextEditor {
function existingEditorForUri(path) {
// This isn't ideal but realistically iterating through even a few hundred editors shouldn't be a

@@ -41,5 +57,14 @@ // real problem. And if you have more than a few hundred you probably have bigger problems.

*/
export function existingEditorForBuffer(
buffer: atom$TextBuffer,
): ?atom$TextEditor {
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the LICENSE file in
* the root directory of this source tree.
*
*
* @format
*/
function existingEditorForBuffer(buffer) {
// This isn't ideal but realistically iterating through even a few hundred editors shouldn't be a

@@ -56,13 +81,11 @@ // real problem. And if you have more than a few hundred you probably have bigger problems.

export function getViewOfEditor(
editor: atom$TextEditor,
): atom$TextEditorElement {
function getViewOfEditor(editor) {
return atom.views.getView(editor);
}
export function getScrollTop(editor: atom$TextEditor): number {
function getScrollTop(editor) {
return getViewOfEditor(editor).getScrollTop();
}
export function setScrollTop(editor: atom$TextEditor, scrollTop: number): void {
function setScrollTop(editor, scrollTop) {
getViewOfEditor(editor).setScrollTop(scrollTop);

@@ -78,32 +101,21 @@ }

*/
export function setPositionAndScroll(
editor: atom$TextEditor,
position: atom$Point,
scrollTop: number,
): void {
editor.setCursorBufferPosition(position, {autoscroll: false});
function setPositionAndScroll(editor, position, scrollTop) {
editor.setCursorBufferPosition(position, { autoscroll: false });
setScrollTop(editor, scrollTop);
}
export function getCursorPositions(
editor: atom$TextEditor,
): Observable<atom$Point> {
function getCursorPositions(editor) {
// This will behave strangely in the face of multiple cursors. Consider supporting multiple
// cursors in the future.
const cursor = editor.getCursors()[0];
invariant(cursor != null);
return Observable.merge(
Observable.of(cursor.getBufferPosition()),
observableFromSubscribeFunction(
cursor.onDidChangePosition.bind(cursor),
).map(event => event.newBufferPosition),
);
if (!(cursor != null)) {
throw new Error('Invariant violation: "cursor != null"');
}
return _rxjsBundlesRxMinJs.Observable.merge(_rxjsBundlesRxMinJs.Observable.of(cursor.getBufferPosition()), (0, (_event || _load_event()).observableFromSubscribeFunction)(cursor.onDidChangePosition.bind(cursor)).map(event => event.newBufferPosition));
}
export function observeEditorDestroy(
editor: atom$TextEditor,
): Observable<atom$TextEditor> {
return observableFromSubscribeFunction(editor.onDidDestroy.bind(editor))
.map(event => editor)
.take(1);
function observeEditorDestroy(editor) {
return (0, (_event || _load_event()).observableFromSubscribeFunction)(editor.onDidDestroy.bind(editor)).map(event => editor).take(1);
}

@@ -116,3 +128,3 @@

// TODO: https://github.com/atom/atom/issues/9237.
export function enforceReadOnly(textEditor: atom$TextEditor): void {
function enforceReadOnly(textEditor) {
const noop = () => {};

@@ -135,7 +147,7 @@

function passReadOnlyException(functionName: string) {
const buffer: any = textBuffer;
function passReadOnlyException(functionName) {
const buffer = textBuffer;
const originalFunction = buffer[functionName];
buffer[functionName] = function() {
buffer[functionName] = function () {
textBuffer.applyChange = originalApplyChange;

@@ -152,6 +164,3 @@ const result = originalFunction.apply(textBuffer, arguments);

// after mounting an editor to the workspace - here, that's watched and reset to `false`.
export function enforceSoftWrap(
editor: atom$TextEditor,
enforcedSoftWrap: boolean,
): IDisposable {
function enforceSoftWrap(editor, enforcedSoftWrap) {
editor.setSoftWrapped(enforcedSoftWrap);

@@ -174,5 +183,3 @@ return editor.onDidChangeSoftWrapped(softWrapped => {

*/
export function observeTextEditors(
callback: (editor: atom$TextEditor) => mixed,
): IDisposable {
function observeTextEditors(callback) {
// The one place where atom.workspace.observeTextEditors needs to be used.

@@ -190,8 +197,6 @@ // eslint-disable-next-line nuclide-internal/atom-apis

*/
export function isValidTextEditor(item: mixed): boolean {
function isValidTextEditor(item) {
// eslint-disable-next-line nuclide-internal/atom-apis
if (atom.workspace.isTextEditor(item)) {
return !nuclideUri.isBrokenDeserializedUri(
((item: any): atom$TextEditor).getPath(),
);
return !(_nuclideUri || _load_nuclideUri()).default.isBrokenDeserializedUri(item.getPath());
}

@@ -201,18 +206,9 @@ return false;

export function centerScrollToBufferLine(
textEditorElement: atom$TextEditorElement,
bufferLineNumber: number,
): void {
function centerScrollToBufferLine(textEditorElement, bufferLineNumber) {
const textEditor = textEditorElement.getModel();
const pixelPositionTop = textEditorElement.pixelPositionForBufferPosition([
bufferLineNumber,
0,
]).top;
const pixelPositionTop = textEditorElement.pixelPositionForBufferPosition([bufferLineNumber, 0]).top;
// Manually calculate the scroll location, instead of using
// `textEditor.scrollToBufferPosition([lineNumber, 0], {center: true})`
// because that API to wouldn't center the line if it was in the visible screen range.
const scrollTop =
pixelPositionTop +
textEditor.getLineHeightInPixels() / 2 -
textEditorElement.clientHeight / 2;
const scrollTop = pixelPositionTop + textEditor.getLineHeightInPixels() / 2 - textEditorElement.clientHeight / 2;
textEditorElement.setScrollTop(Math.max(scrollTop, 1));

@@ -223,4 +219,4 @@

textEditor.setCursorBufferPosition([bufferLineNumber, 0], {
autoscroll: false,
autoscroll: false
});
}
}

@@ -0,1 +1,34 @@

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.__TEST__ = exports.TextEventDispatcher = undefined;
exports.observeTextEditorEvents = observeTextEditorEvents;
var _atom = require('atom');
var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js');
var _debounce;
function _load_debounce() {
return _debounce = _interopRequireDefault(require('nuclide-commons/debounce'));
}
var _event;
function _load_event() {
return _event = require('nuclide-commons/event');
}
var _textEditor;
function _load_textEditor() {
return _textEditor = require('./text-editor');
}
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
// A reload changes the text in the buffer, so it should trigger a refresh.
/**

@@ -8,18 +41,6 @@ * Copyright (c) 2015-present, Facebook, Inc.

*
* @flow
*
* @format
*/
import invariant from 'assert';
import {Disposable, CompositeDisposable} from 'atom';
import {Observable} from 'rxjs';
import debounce from 'nuclide-commons/debounce';
import {observableFromSubscribeFunction} from 'nuclide-commons/event';
import {observeTextEditors} from './text-editor';
type EventCallback = (editor: TextEditor) => mixed;
type Event = 'did-reload' | 'did-change' | 'did-save' | 'did-open';
// A reload changes the text in the buffer, so it should trigger a refresh.
const FILE_CHANGE_EVENTS = ['did-change', 'did-reload', 'did-open'];

@@ -36,11 +57,5 @@

*/
class TextCallbackContainer<CallbackArg> {
class TextCallbackContainer {
// grammar -> event -> callback
// invariant: no empty maps or sets (they should be removed instead)
_callbacks: Map<string, Map<Event, Set<(arg: CallbackArg) => mixed>>>;
// event -> callback
// invariant: no keys mapping to empty sets (they should be removed instead)
_allGrammarCallbacks: Map<Event, Set<(arg: CallbackArg) => mixed>>;
constructor() {

@@ -51,12 +66,10 @@ this._callbacks = new Map();

getCallbacks(
grammar: string,
event: Event,
): Set<(arg: CallbackArg) => mixed> {
// event -> callback
// invariant: no keys mapping to empty sets (they should be removed instead)
getCallbacks(grammar, event) {
const eventMap = this._callbacks.get(grammar);
const callbacksForGrammar = this._getCallbacksFromEventMap(eventMap, event);
const callbacksForAll = this._getCallbacksFromEventMap(
this._allGrammarCallbacks,
event,
);
const callbacksForAll = this._getCallbacksFromEventMap(this._allGrammarCallbacks, event);
const resultSet = new Set();

@@ -71,10 +84,7 @@ const add = callback => {

isEmpty(): boolean {
isEmpty() {
return this._callbacks.size === 0 && this._allGrammarCallbacks.size === 0;
}
_getCallbacksFromEventMap(
eventMap: ?Map<Event, Set<(arg: CallbackArg) => mixed>>,
event: Event,
): Set<(arg: CallbackArg) => mixed> {
_getCallbacksFromEventMap(eventMap, event) {
if (!eventMap) {

@@ -90,7 +100,3 @@ return new Set();

addCallback(
grammarScopes: Iterable<string> | 'all',
events: Iterable<Event>,
callback: (arg: CallbackArg) => mixed,
): void {
addCallback(grammarScopes, events, callback) {
if (grammarScopes === 'all') {

@@ -112,7 +118,3 @@ this._addToEventMap(this._allGrammarCallbacks, events, callback);

// empty maps or sets in this._callbacks
removeCallback(
grammarScopes: Iterable<string> | 'all',
events: Iterable<Event>,
callback: (arg: CallbackArg) => mixed,
): void {
removeCallback(grammarScopes, events, callback) {
if (grammarScopes === 'all') {

@@ -123,3 +125,7 @@ this._removeFromEventMap(this._allGrammarCallbacks, events, callback);

const eventMap = this._callbacks.get(grammarScope);
invariant(eventMap);
if (!eventMap) {
throw new Error('Invariant violation: "eventMap"');
}
this._removeFromEventMap(eventMap, events, callback);

@@ -133,7 +139,3 @@ if (eventMap.size === 0) {

_addToEventMap(
eventMap: Map<Event, Set<(arg: CallbackArg) => mixed>>,
events: Iterable<Event>,
callback: (arg: CallbackArg) => mixed,
): void {
_addToEventMap(eventMap, events, callback) {
for (const event of events) {

@@ -149,10 +151,10 @@ let callbackSet = eventMap.get(event);

_removeFromEventMap(
eventMap: Map<Event, Set<(arg: CallbackArg) => mixed>>,
events: Iterable<Event>,
callback: (arg: CallbackArg) => mixed,
): void {
_removeFromEventMap(eventMap, events, callback) {
for (const event of events) {
const callbackSet = eventMap.get(event);
invariant(callbackSet);
if (!callbackSet) {
throw new Error('Invariant violation: "callbackSet"');
}
callbackSet.delete(callback);

@@ -183,9 +185,4 @@ if (callbackSet.size === 0) {

*/
export class TextEventDispatcher {
_callbackContainer: TextCallbackContainer<TextEditor>;
class TextEventDispatcher {
_editorListenerDisposable: ?CompositeDisposable;
_pendingEvents: WeakMap<atom$TextBuffer, Set<Event>>;
constructor() {

@@ -197,7 +194,3 @@ this._callbackContainer = new TextCallbackContainer();

_onEvents(
grammarScopes: Iterable<string> | 'all',
events: Iterable<Event>,
callback: EventCallback,
) {
_onEvents(grammarScopes, events, callback) {
if (this._callbackContainer.isEmpty()) {

@@ -208,14 +201,6 @@ this._registerEditorListeners();

// (particularly on startup).
const debouncedCallback = debounce(callback, 50, true);
this._callbackContainer.addCallback(
grammarScopes,
events,
debouncedCallback,
);
const disposables = new Disposable(() => {
this._callbackContainer.removeCallback(
grammarScopes,
events,
debouncedCallback,
);
const debouncedCallback = (0, (_debounce || _load_debounce()).default)(callback, 50, true);
this._callbackContainer.addCallback(grammarScopes, events, debouncedCallback);
const disposables = new _atom.Disposable(() => {
this._callbackContainer.removeCallback(grammarScopes, events, debouncedCallback);
if (this._callbackContainer.isEmpty()) {

@@ -228,26 +213,20 @@ this._deregisterEditorListeners();

onFileChange(
grammarScopes: Iterable<string>,
callback: EventCallback,
): IDisposable {
onFileChange(grammarScopes, callback) {
return this._onEvents(grammarScopes, FILE_CHANGE_EVENTS, callback);
}
onAnyFileChange(callback: EventCallback): IDisposable {
onAnyFileChange(callback) {
return this._onEvents('all', FILE_CHANGE_EVENTS, callback);
}
onFileSave(
grammarScopes: Iterable<string>,
callback: EventCallback,
): IDisposable {
onFileSave(grammarScopes, callback) {
return this._onEvents(grammarScopes, FILE_SAVE_EVENTS, callback);
}
onAnyFileSave(callback: EventCallback): IDisposable {
onAnyFileSave(callback) {
return this._onEvents('all', FILE_SAVE_EVENTS, callback);
}
_registerEditorListeners(): void {
_registerEditorListeners() {
if (!this._editorListenerDisposable) {
this._editorListenerDisposable = new CompositeDisposable();
this._editorListenerDisposable = new _atom.CompositeDisposable();
}

@@ -257,43 +236,31 @@

// pending events for the newly-focused TextEditor.
this._getEditorListenerDisposable().add(
atom.workspace.onDidChangeActivePaneItem(() => {
const currentEditor = atom.workspace.getActiveTextEditor();
if (currentEditor) {
const pendingEvents = this._pendingEvents.get(
currentEditor.getBuffer(),
);
if (pendingEvents) {
for (const event of pendingEvents) {
this._dispatchEvents(currentEditor, event);
}
this._pendingEvents.delete(currentEditor.getBuffer());
this._getEditorListenerDisposable().add(atom.workspace.onDidChangeActivePaneItem(() => {
const currentEditor = atom.workspace.getActiveTextEditor();
if (currentEditor) {
const pendingEvents = this._pendingEvents.get(currentEditor.getBuffer());
if (pendingEvents) {
for (const event of pendingEvents) {
this._dispatchEvents(currentEditor, event);
}
this._pendingEvents.delete(currentEditor.getBuffer());
}
}),
);
}
}));
this._getEditorListenerDisposable().add(
observeTextEditors(editor => {
const buffer = editor.getBuffer();
const makeDispatch = (event: Event) => {
return () => {
this._dispatchEvents(editor, event);
};
this._getEditorListenerDisposable().add((0, (_textEditor || _load_textEditor()).observeTextEditors)(editor => {
const buffer = editor.getBuffer();
const makeDispatch = event => {
return () => {
this._dispatchEvents(editor, event);
};
this._getEditorListenerDisposable().add(
buffer.onDidStopChanging(makeDispatch('did-change')),
);
this._getEditorListenerDisposable().add(
buffer.onDidSave(makeDispatch('did-save')),
);
this._getEditorListenerDisposable().add(
buffer.onDidReload(makeDispatch('did-reload')),
);
// During reload, many text editors are opened simultaneously.
// Due to the debounce on the event callback, this means that many editors never receive
// a 'did-open' event. To work around this, defer editor open events so that simultaneous
// open events are properly registered as pending.
setImmediate(() => this._dispatchEvents(editor, 'did-open'));
}),
);
};
this._getEditorListenerDisposable().add(buffer.onDidStopChanging(makeDispatch('did-change')));
this._getEditorListenerDisposable().add(buffer.onDidSave(makeDispatch('did-save')));
this._getEditorListenerDisposable().add(buffer.onDidReload(makeDispatch('did-reload')));
// During reload, many text editors are opened simultaneously.
// Due to the debounce on the event callback, this means that many editors never receive
// a 'did-open' event. To work around this, defer editor open events so that simultaneous
// open events are properly registered as pending.
setImmediate(() => this._dispatchEvents(editor, 'did-open'));
}));
}

@@ -308,9 +275,6 @@

_dispatchEvents(editor: TextEditor, event: Event): void {
_dispatchEvents(editor, event) {
const currentEditor = atom.workspace.getActiveTextEditor();
if (currentEditor && editor === currentEditor) {
const callbacks = this._callbackContainer.getCallbacks(
editor.getGrammar().scopeName,
event,
);
const callbacks = this._callbackContainer.getCallbacks(editor.getGrammar().scopeName, event);
for (const callback of callbacks) {

@@ -322,6 +286,3 @@ callback(editor);

// multiple panes have the same file open.
} else if (
!currentEditor ||
editor.getBuffer() !== currentEditor.getBuffer()
) {
} else if (!currentEditor || editor.getBuffer() !== currentEditor.getBuffer()) {
// Trigger this event next time we switch to an editor with this buffer.

@@ -338,5 +299,9 @@ const buffer = editor.getBuffer();

_getEditorListenerDisposable(): CompositeDisposable {
_getEditorListenerDisposable() {
const disposable = this._editorListenerDisposable;
invariant(disposable, 'TextEventDispatcher disposable is not initialized');
if (!disposable) {
throw new Error('TextEventDispatcher disposable is not initialized');
}
return disposable;

@@ -346,27 +311,17 @@ }

export function observeTextEditorEvents(
grammarScopes: Iterable<string> | 'all',
events: 'changes' | 'saves',
): Observable<atom$TextEditor> {
return Observable.defer(() => {
exports.TextEventDispatcher = TextEventDispatcher;
function observeTextEditorEvents(grammarScopes, events) {
return _rxjsBundlesRxMinJs.Observable.defer(() => {
const dispatcher = new TextEventDispatcher();
if (events === 'changes') {
if (grammarScopes === 'all') {
return observableFromSubscribeFunction(cb =>
dispatcher.onAnyFileChange(cb),
);
return (0, (_event || _load_event()).observableFromSubscribeFunction)(cb => dispatcher.onAnyFileChange(cb));
} else {
return observableFromSubscribeFunction(cb =>
dispatcher.onFileChange(grammarScopes, cb),
);
return (0, (_event || _load_event()).observableFromSubscribeFunction)(cb => dispatcher.onFileChange(grammarScopes, cb));
}
} else {
if (grammarScopes === 'all') {
return observableFromSubscribeFunction(cb =>
dispatcher.onAnyFileSave(cb),
);
return (0, (_event || _load_event()).observableFromSubscribeFunction)(cb => dispatcher.onAnyFileSave(cb));
} else {
return observableFromSubscribeFunction(cb =>
dispatcher.onFileSave(grammarScopes, cb),
);
return (0, (_event || _load_event()).observableFromSubscribeFunction)(cb => dispatcher.onFileSave(grammarScopes, cb));
}

@@ -377,4 +332,4 @@ }

export const __TEST__ = {
TextCallbackContainer,
};
const __TEST__ = exports.__TEST__ = {
TextCallbackContainer
};

@@ -0,2 +1,32 @@

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getDocksWorkspaceViewsService = getDocksWorkspaceViewsService;
exports.consumeWorkspaceViewsCompat = consumeWorkspaceViewsCompat;
var _atom = require('atom');
var _semver;
function _load_semver() {
return _semver = _interopRequireDefault(require('semver'));
}
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* The object used as items in locations. This is based on the supported interface for items in Atom
* panes. That way, we maintain compatibility with Atom (upstream?) and can put them in panes as-is.
*
* The truth is that these models can have any methods they want. Packages define ad-hoc protocols
* and check to see if the item implements them. For example, atom-tabs will call `getIconName()` if
* it exists. We have some of our own optional methods which, for clarity's sake, are defined here,
* even though they're only used by some of our location packages.
*
* IMPORTANT: All properties and methods must be optional so that we maintain compatibility with
* non-nuclide items.
*/
/**
* Copyright (c) 2015-present, Facebook, Inc.

@@ -8,3 +38,3 @@ * All rights reserved.

*
* @flow
*
* @format

@@ -20,69 +50,7 @@ */

import {Disposable} from 'atom';
import semver from 'semver';
/**
* The object used as items in locations. This is based on the supported interface for items in Atom
* panes. That way, we maintain compatibility with Atom (upstream?) and can put them in panes as-is.
*
* The truth is that these models can have any methods they want. Packages define ad-hoc protocols
* and check to see if the item implements them. For example, atom-tabs will call `getIconName()` if
* it exists. We have some of our own optional methods which, for clarity's sake, are defined here,
* even though they're only used by some of our location packages.
*
* IMPORTANT: All properties and methods must be optional so that we maintain compatibility with
* non-nuclide items.
*/
export type Viewable = atom$PaneItem & {
// Used by PanelLocation to get an initial size for the panel.
+getPreferredHeight?: () => number,
+getPreferredWidth?: () => number,
+didChangeVisibility?: (visible: boolean) => void,
+getDefaultLocation?: () => string,
};
export type Opener = (uri: string) => ?Viewable;
export type OpenOptions = {
activateItem?: boolean,
activateLocation?: boolean,
searchAllPanes?: boolean,
};
export type Location = {
activate(): void,
activateItem(item: Object): void,
addItem(item: Object): void,
destroy(): void,
destroyItem(item: Object): void,
getItems(): Array<Viewable>,
hideItem(item: Viewable): void,
itemIsVisible(item: Viewable): boolean,
serialize(): ?Object,
onDidAddItem(cb: (item: Viewable) => void): IDisposable,
};
export type LocationFactory = {
id: string,
create(serializedState: ?Object): Location,
};
export type ToggleOptions = {
visible?: ?boolean,
};
export type WorkspaceViewsService = {
addOpener(opener: Opener): IDisposable,
destroyWhere(predicate: (item: Viewable) => boolean): void,
open(uri: string, options?: OpenOptions): void,
registerLocation(factory: LocationFactory): IDisposable,
toggle(uri: string, options?: ToggleOptions): void,
};
export function getDocksWorkspaceViewsService() {
function getDocksWorkspaceViewsService() {
return {
registerLocation: () => new Disposable(() => {}),
registerLocation: () => new _atom.Disposable(() => {}),
addOpener: opener => atom.workspace.addOpener(opener),
destroyWhere(predicate: (item: Viewable) => boolean) {
destroyWhere(predicate) {
atom.workspace.getPanes().forEach(pane => {

@@ -96,18 +64,14 @@ pane.getItems().forEach(item => {

},
open(uri: string, options?: Object): void {
open(uri, options) {
// eslint-disable-next-line nuclide-internal/atom-apis
atom.workspace.open(uri, options);
},
toggle(uri: string, options?: ?ToggleOptions): void {
toggle(uri, options) {
const visible = options && options.visible;
if (visible === true) {
// eslint-disable-next-line nuclide-internal/atom-apis
atom.workspace.open(uri, {searchAllPanes: true});
atom.workspace.open(uri, { searchAllPanes: true });
} else if (visible === false) {
// TODO: Add `atom.workspace.hide()` and use that instead.
const hasItem = atom.workspace
.getPaneItems()
.some(
item => typeof item.getURI === 'function' && item.getURI() === uri,
);
const hasItem = atom.workspace.getPaneItems().some(item => typeof item.getURI === 'function' && item.getURI() === uri);
if (hasItem) {

@@ -123,18 +87,12 @@ // TODO(matthewwithanm): Add this to the Flow defs once docks land

}
},
}
};
}
export function consumeWorkspaceViewsCompat(
callback: (service: WorkspaceViewsService) => IDisposable,
): IDisposable {
if (semver.gte(atom.getVersion(), '1.17.0')) {
function consumeWorkspaceViewsCompat(callback) {
if ((_semver || _load_semver()).default.gte(atom.getVersion(), '1.17.0')) {
callback(getDocksWorkspaceViewsService());
return new Disposable();
return new _atom.Disposable();
}
return atom.packages.serviceHub.consume(
'nuclide.workspace-views',
'0.0.0',
callback,
);
}
return atom.packages.serviceHub.consume('nuclide.workspace-views', '0.0.0', callback);
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc