nuclide-commons-atom
Advanced tools
Comparing version 0.7.0 to 0.7.1
@@ -1,75 +0,128 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });var _asyncToGenerator = _interopRequireDefault(require('async-to-generator')); | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
var _asyncToGenerator = _interopRequireDefault(require('async-to-generator')); | ||
var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js'); | ||
var _debounced; | ||
function _load_debounced() { | ||
return _debounced = require('./debounced'); | ||
} | ||
var _UniversalDisposable; | ||
function _load_UniversalDisposable() { | ||
return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable')); | ||
} | ||
var _event; | ||
function _load_event() { | ||
return _event = require('nuclide-commons/event'); | ||
} | ||
var _observable; | ||
function _load_observable() { | ||
return _observable = require('nuclide-commons/observable'); | ||
} | ||
var _log4js; | ||
function _load_log4js() { | ||
return _log4js = require('log4js'); | ||
} | ||
var _ProviderRegistry; | ||
function _load_ProviderRegistry() { | ||
return _ProviderRegistry = _interopRequireDefault(require('./ProviderRegistry')); | ||
} | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js');var _debounced; | ||
function _load_debounced() {return _debounced = require('./debounced');}var _UniversalDisposable; | ||
function _load_UniversalDisposable() {return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable'));}var _event; | ||
function _load_event() {return _event = require('nuclide-commons/event');}var _observable; | ||
function _load_observable() {return _observable = require('nuclide-commons/observable');}var _log4js; | ||
function _load_log4js() {return _log4js = require('log4js');}var _ProviderRegistry; | ||
function _load_ProviderRegistry() {return _ProviderRegistry = _interopRequireDefault(require('./ProviderRegistry'));}function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} | ||
const DEFAULT_CONFIG = { | ||
updateOnEdit: true | ||
}; /** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ | ||
updateOnEdit: true }; /** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ /** | ||
* ActiveEditorRegistry provides abstractions for creating services that operate | ||
* on text editor contents. | ||
*/function getConcreteConfig(config) {return Object.assign({}, DEFAULT_CONFIG, config);}class ActiveEditorRegistry { | ||
/** | ||
* ActiveEditorRegistry provides abstractions for creating services that operate | ||
* on text editor contents. | ||
*/ | ||
function getConcreteConfig(config) { | ||
return Object.assign({}, DEFAULT_CONFIG, config); | ||
} | ||
class ActiveEditorRegistry { | ||
constructor(resultFunction, config = {}, eventSources = {}) { | ||
constructor( | ||
resultFunction, | ||
config = {}, | ||
eventSources = {}) | ||
{ | ||
this._config = getConcreteConfig(config); | ||
@@ -80,8 +133,15 @@ this._resultFunction = resultFunction; | ||
this._resultsStream = this._createResultsStream({ | ||
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); | ||
}) | ||
}); | ||
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); | ||
}) }); | ||
} | ||
@@ -106,3 +166,6 @@ | ||
} | ||
return _rxjsBundlesRxMinJs.Observable.concat(_rxjsBundlesRxMinJs.Observable.of(editor), this._newProviderEvents.mapTo(editor)); | ||
return _rxjsBundlesRxMinJs.Observable.concat( | ||
_rxjsBundlesRxMinJs.Observable.of(editor), | ||
this._newProviderEvents.mapTo(editor)); | ||
}); | ||
@@ -121,4 +184,9 @@ const results = repeatedEditors.switchMap(editorArg => { | ||
kind: 'pane-change', | ||
editor | ||
}), _rxjsBundlesRxMinJs.Observable.fromPromise(this._getResultForEditor(this._getProviderForEditor(editor), editor)), this._resultsForEditor(editor, eventSources)); | ||
editor }), | ||
_rxjsBundlesRxMinJs.Observable.fromPromise( | ||
this._getResultForEditor(this._getProviderForEditor(editor), editor)), | ||
this._resultsForEditor(editor, eventSources)); | ||
}); | ||
@@ -128,6 +196,12 @@ return (0, (_observable || _load_observable()).cacheWhileSubscribed)(results); | ||
_resultsForEditor(editor, eventSources) { | ||
_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 _rxjsBundlesRxMinJs.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); | ||
@@ -146,3 +220,5 @@ if (provider != null) { | ||
// $FlowIssue: {kind: edit | save} <=> {kind: edit} | {kind: save} | ||
_rxjsBundlesRxMinJs.Observable.of({ kind: event, editor }), _rxjsBundlesRxMinJs.Observable.fromPromise(this._getResultForEditor(provider, editor))); | ||
_rxjsBundlesRxMinJs.Observable.of({ kind: event, editor }), | ||
_rxjsBundlesRxMinJs.Observable.fromPromise(this._getResultForEditor(provider, editor))); | ||
}); | ||
@@ -155,11 +231,11 @@ } | ||
_getResultForEditor(provider, editor) { | ||
var _this = this; | ||
return (0, _asyncToGenerator.default)(function* () { | ||
_getResultForEditor( | ||
provider, | ||
editor) | ||
{var _this = this;return (0, _asyncToGenerator.default)(function* () { | ||
if (provider == null) { | ||
return { | ||
kind: 'no-provider', | ||
grammar: editor.getGrammar() | ||
}; | ||
grammar: editor.getGrammar() }; | ||
} | ||
@@ -171,14 +247,14 @@ try { | ||
provider, | ||
editor | ||
}; | ||
editor }; | ||
} catch (e) { | ||
(0, (_log4js || _load_log4js()).getLogger)(_this.constructor.name).error(`Error from provider for ${editor.getGrammar().scopeName}`, 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; | ||
kind: 'provider-error' }; | ||
}})(); | ||
}}exports.default = ActiveEditorRegistry; |
@@ -1,33 +0,34 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.default = | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.default = consumeFirstProvider; | ||
/** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ | ||
/** | ||
* The module formerly known as "service-hub-plus". Provides a workaround for | ||
* https://github.com/atom/service-hub/issues/6 | ||
*/ | ||
function consumeFirstProvider(keyPath, version = '0.0.0') { | ||
return new Promise((resolve, reject) => { | ||
const subscription = atom.packages.serviceHub.consume(keyPath, version, provider => { | ||
process.nextTick(() => { | ||
resolve(provider); | ||
subscription.dispose(); | ||
}); | ||
}); | ||
consumeFirstProvider; /** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ /** | ||
* The module formerly known as "service-hub-plus". Provides a workaround for | ||
* https://github.com/atom/service-hub/issues/6 | ||
*/function consumeFirstProvider(keyPath, version = '0.0.0') {return new Promise((resolve, reject) => {const subscription = atom.packages.serviceHub.consume(keyPath, version, provider => {process.nextTick(() => {resolve(provider);subscription.dispose();});}); | ||
}); | ||
} |
@@ -1,238 +0,311 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports. | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.showMenuForEvent = showMenuForEvent; | ||
var _UniversalDisposable; | ||
function _load_UniversalDisposable() { | ||
return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable')); | ||
} | ||
var _electron = require('electron'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
/** | ||
* This class represents a collection of context menu items that have been registered with Atom's | ||
* ContextMenuManager under a single CSS selector. These items are ordered based on the specified | ||
* priority with which they are added to this object. (The CSS selector is either specified | ||
* explicitly via the `cssSelector` property of the RootMenuOptions passed to the constructor, or | ||
* implicitly via the `parent` property of the SubmenuOptions passed to the constructor.) | ||
* | ||
* This is in contrast to Atom's ContextMenuManager, which relies on the specificity of the CSS | ||
* selector for a menu item to determine its precedence. The motivation behind this approach is to | ||
* provide a total order on menu item ordering rather than a partial order. As such, this class | ||
* serves as an adapter between the numeric priority model and ContextMenuManager's model. | ||
* | ||
* Note that this class also provides support for submenu items. This requires Atom 1.6 or later | ||
* because it relies on this fix: https://github.com/atom/atom/pull/10486. | ||
*/ | ||
/** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ | ||
class ContextMenu { | ||
/** | ||
* List of items that have been added to this context menu in the order they were added. | ||
* Note that this list does not get sorted: only a filtered version of it does. | ||
* Further, this list is mutated heavily, but it is never reassigned. | ||
*/ | ||
constructor(menuOptions) { | ||
this._menuOptions = menuOptions; | ||
this._items = []; | ||
this._needsSort = false; | ||
this._sort = this._sort.bind(this); | ||
this._disposable = null; | ||
} | ||
/** | ||
* @return true if this menu does not contain any items; otherwise, returns false. Note this will | ||
* return true if it contains only empty submenu items. | ||
*/ | ||
/** | ||
* 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; | ||
} | ||
/** | ||
* Adds the specified item to this contenxt menu. | ||
* | ||
* Items with lower priority values appear earlier in the context menu | ||
* (i.e., items appear in numerical order with respect to priority). | ||
* | ||
* @return object whose dispose() method can be used to remove the menu item from this object. | ||
*/ | ||
addItem(item, priority) { | ||
const value = { type: 'item', item, priority }; | ||
return this._addItemToList(value); | ||
} | ||
/** | ||
* Adds the specified submenu to this contenxt menu. | ||
* | ||
* Items with lower priority values appear earlier in the context menu | ||
* (i.e., items appear in numerical order with respect to priority). | ||
* | ||
* @return object whose dispose() method can be used to remove the submenu from this object. | ||
*/ | ||
addSubmenu(contextMenu, priority) { | ||
const value = { type: 'menu', menu: contextMenu, priority }; | ||
return this._addItemToList(value); | ||
} | ||
_addItemToList(value) { | ||
this._items.push(value); | ||
this._needsSort = true; | ||
process.nextTick(this._sort); | ||
// TODO(mbolin): Ideally, this Disposable should be garbage-collected if this ContextMenu is | ||
// disposed. | ||
return new (_UniversalDisposable || _load_UniversalDisposable()).default(() => { | ||
const index = this._items.indexOf(value); | ||
this._items.splice(index, 1); | ||
// We need to invoke _sort for the management of this._disposable and atom.contextMenu.add. | ||
this._needsSort = true; | ||
this._sort(); | ||
}); | ||
} | ||
/** | ||
* This method must be invoked after this._items has been modified. If necessary, it will remove | ||
* all items that this object previously registered with Atom's ContextMenuManager. Then it will | ||
* re-register everything in this._items once it has been sorted. | ||
*/ | ||
_sort() { | ||
if (!this._needsSort) { | ||
return; | ||
} | ||
this._needsSort = false; | ||
if (this._disposable != null) { | ||
this._disposable.dispose(); | ||
} | ||
const menuOptions = this._menuOptions; | ||
if (menuOptions.type === 'root') { | ||
const items = this._sortAndFilterItems(); | ||
this._disposable = atom.contextMenu.add({ | ||
[menuOptions.cssSelector]: items.map(this._contextMenuItemForInternalItem, this) | ||
}); | ||
} else if (menuOptions.type === 'submenu') { | ||
// Tell the parent menu to sort itself. | ||
menuOptions.parent._needsSort = true; | ||
menuOptions.parent._sort(); | ||
} | ||
} | ||
/** Translates this object's internal representation of a menu item to Atom's representation. */ | ||
_contextMenuItemForInternalItem(internalItem) { | ||
if (internalItem.type === 'item') { | ||
return internalItem.item; | ||
} else if (internalItem.type === 'menu') { | ||
// Note that due to our own strict renaming rules, this must be a private method instead of a | ||
// static function because of the access to _menuOptions and _items. | ||
const menuOptions = internalItem.menu._menuOptions; | ||
if (!(menuOptions.type === 'submenu')) { | ||
throw new Error('Invariant violation: "menuOptions.type === \'submenu\'"'); | ||
} | ||
const items = internalItem.menu._sortAndFilterItems(); | ||
return { | ||
label: menuOptions.label, | ||
submenu: items.map(this._contextMenuItemForInternalItem, this), | ||
shouldDisplay: menuOptions.shouldDisplay | ||
}; | ||
} else { | ||
if (!false) { | ||
throw new Error('Invariant violation: "false"'); | ||
} | ||
} | ||
} | ||
_sortAndFilterItems() { | ||
const items = this._items.filter(item => { | ||
if (item.type === 'item') { | ||
return true; | ||
} else if (item.type === 'menu') { | ||
const contextMenu = item.menu; | ||
return !contextMenu.isEmpty(); | ||
} | ||
}); | ||
items.sort(compareInternalItems); | ||
return items; | ||
} | ||
/** Removes all items this object has added to Atom's ContextMenuManager. */ | ||
dispose() { | ||
this._needsSort = false; | ||
if (this._disposable != null) { | ||
this._disposable.dispose(); | ||
} | ||
this._items.length = 0; | ||
} | ||
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) && | ||
// flowlint-next-line sketchy-null-mixed:off | ||
event.detail[0] && event.detail[0].contextCommand; | ||
} | ||
} | ||
exports.default = ContextMenu; /** Comparator used to sort menu items by priority: lower priorities appear earlier. */ | ||
function compareInternalItems(a, b) { | ||
return a.priority - b.priority; | ||
} | ||
/** | ||
* Shows the provided menu template. This will result in [an extra call to `templateForEvent()`][1], | ||
* but it means that we still go through `showMenuForEvent()`, maintaining its behavior wrt | ||
* (a)synchronousness. See atom/atom#13398. | ||
* | ||
* [1]: https://github.com/atom/atom/blob/v1.13.0/src/context-menu-manager.coffee#L200 | ||
*/ | ||
function showMenuForEvent(event, menuTemplate) { | ||
if (!(_electron.remote != null)) { | ||
throw new Error('Invariant violation: "remote != null"'); | ||
} | ||
const win = _electron.remote.getCurrentWindow(); | ||
const originalEmit = win.emit; | ||
const restore = () => { | ||
win.emit = originalEmit; | ||
}; | ||
win.emit = (eventType, ...args) => { | ||
if (eventType !== 'context-menu') { | ||
return originalEmit(eventType, ...args); | ||
} | ||
const result = originalEmit('context-menu', menuTemplate); | ||
restore(); | ||
return result; | ||
}; | ||
atom.contextMenu.showForEvent(event); | ||
return new (_UniversalDisposable || _load_UniversalDisposable()).default(restore); | ||
} | ||
showMenuForEvent = showMenuForEvent;var _UniversalDisposable;function _load_UniversalDisposable() {return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable'));}var _electron = require('electron');function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} /** | ||
* This class represents a collection of context menu items that have been registered with Atom's | ||
* ContextMenuManager under a single CSS selector. These items are ordered based on the specified | ||
* priority with which they are added to this object. (The CSS selector is either specified | ||
* explicitly via the `cssSelector` property of the RootMenuOptions passed to the constructor, or | ||
* implicitly via the `parent` property of the SubmenuOptions passed to the constructor.) | ||
* | ||
* This is in contrast to Atom's ContextMenuManager, which relies on the specificity of the CSS | ||
* selector for a menu item to determine its precedence. The motivation behind this approach is to | ||
* provide a total order on menu item ordering rather than a partial order. As such, this class | ||
* serves as an adapter between the numeric priority model and ContextMenuManager's model. | ||
* | ||
* Note that this class also provides support for submenu items. This requires Atom 1.6 or later | ||
* because it relies on this fix: https://github.com/atom/atom/pull/10486. | ||
*/ /** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/class ContextMenu {/** | ||
* List of items that have been added to this context menu in the order they were added. | ||
* Note that this list does not get sorted: only a filtered version of it does. | ||
* Further, this list is mutated heavily, but it is never reassigned. | ||
*/constructor(menuOptions) {this._menuOptions = menuOptions;this._items = [];this._needsSort = false;this._sort = this._sort.bind(this);this._disposable = null;} /** | ||
* @return true if this menu does not contain any items; otherwise, returns false. Note this will | ||
* return true if it contains only empty submenu items. | ||
*/ /** | ||
* 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;} /** | ||
* Adds the specified item to this contenxt menu. | ||
* | ||
* Items with lower priority values appear earlier in the context menu | ||
* (i.e., items appear in numerical order with respect to priority). | ||
* | ||
* @return object whose dispose() method can be used to remove the menu item from this object. | ||
*/addItem(item, priority) {const value = { type: 'item', item, priority };return this._addItemToList(value);} /** | ||
* Adds the specified submenu to this contenxt menu. | ||
* | ||
* Items with lower priority values appear earlier in the context menu | ||
* (i.e., items appear in numerical order with respect to priority). | ||
* | ||
* @return object whose dispose() method can be used to remove the submenu from this object. | ||
*/addSubmenu(contextMenu, priority) {const value = { type: 'menu', menu: contextMenu, priority };return this._addItemToList(value);}_addItemToList(value) {this._items.push(value);this._needsSort = true;process.nextTick(this._sort); // TODO(mbolin): Ideally, this Disposable should be garbage-collected if this ContextMenu is | ||
// disposed. | ||
return new (_UniversalDisposable || _load_UniversalDisposable()).default(() => {const index = this._items.indexOf(value);this._items.splice(index, 1); // We need to invoke _sort for the management of this._disposable and atom.contextMenu.add. | ||
this._needsSort = true;this._sort();});} /** | ||
* This method must be invoked after this._items has been modified. If necessary, it will remove | ||
* all items that this object previously registered with Atom's ContextMenuManager. Then it will | ||
* re-register everything in this._items once it has been sorted. | ||
*/_sort() {if (!this._needsSort) {return;}this._needsSort = false;if (this._disposable != null) {this._disposable.dispose();}const menuOptions = this._menuOptions;if (menuOptions.type === 'root') {const items = this._sortAndFilterItems();this._disposable = atom.contextMenu.add({ [menuOptions.cssSelector]: items.map(this._contextMenuItemForInternalItem, this) });} else if (menuOptions.type === 'submenu') {// Tell the parent menu to sort itself. | ||
menuOptions.parent._needsSort = true;menuOptions.parent._sort();}} /** Translates this object's internal representation of a menu item to Atom's representation. */_contextMenuItemForInternalItem(internalItem) {if (internalItem.type === 'item') {return internalItem.item;} else if (internalItem.type === 'menu') {// Note that due to our own strict renaming rules, this must be a private method instead of a | ||
// static function because of the access to _menuOptions and _items. | ||
const menuOptions = internalItem.menu._menuOptions;if (!(menuOptions.type === 'submenu')) {throw new Error('Invariant violation: "menuOptions.type === \'submenu\'"');}const items = internalItem.menu._sortAndFilterItems();return { label: menuOptions.label, submenu: items.map(this._contextMenuItemForInternalItem, this), shouldDisplay: menuOptions.shouldDisplay };} else {if (!false) {throw new Error('Invariant violation: "false"');}}}_sortAndFilterItems() {const items = this._items.filter(item => {if (item.type === 'item') {return true;} else if (item.type === 'menu') {const contextMenu = item.menu;return !contextMenu.isEmpty();}});items.sort(compareInternalItems);return items;} /** Removes all items this object has added to Atom's ContextMenuManager. */dispose() {this._needsSort = false;if (this._disposable != null) {this._disposable.dispose();}this._items.length = 0;}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 (// $FlowFixMe(>=0.68.0) Flow suppress (T27187857) | ||
Array.isArray(event.detail) && // flowlint-next-line sketchy-null-mixed:off | ||
event.detail[0] && event.detail[0].contextCommand);}}exports.default = ContextMenu; /** Comparator used to sort menu items by priority: lower priorities appear earlier. */function compareInternalItems(a, b) {return a.priority - b.priority;} /** | ||
* Shows the provided menu template. This will result in [an extra call to `templateForEvent()`][1], | ||
* but it means that we still go through `showMenuForEvent()`, maintaining its behavior wrt | ||
* (a)synchronousness. See atom/atom#13398. | ||
* | ||
* [1]: https://github.com/atom/atom/blob/v1.13.0/src/context-menu-manager.coffee#L200 | ||
*/function showMenuForEvent(event, menuTemplate) {if (!(_electron.remote != null)) {throw new Error('Invariant violation: "remote != null"');}const win = _electron.remote.getCurrentWindow();const originalEmit = win.emit;const restore = () => {win.emit = originalEmit;};win.emit = (eventType, ...args) => {if (eventType !== 'context-menu') {return originalEmit(eventType, ...args);}const result = originalEmit('context-menu', menuTemplate);restore();return result;};atom.contextMenu.showForEvent(event);return new (_UniversalDisposable || _load_UniversalDisposable()).default(restore);} |
@@ -1,29 +0,26 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.default = | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.default = createPaneContainer; | ||
/** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ | ||
function createPaneContainer() { | ||
const instance = typeof atom.workspace.getCenter === 'function' ? atom.workspace.getCenter().paneContainer : atom.workspace.paneContainer; | ||
const PaneContainer = instance.constructor; | ||
return new PaneContainer({ | ||
viewRegistry: atom.views, | ||
config: atom.config, | ||
applicationDelegate: atom.applicationDelegate, | ||
notificationManager: atom.notifications, | ||
deserializerManager: atom.deserializers | ||
}); | ||
createPaneContainer; /** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/function createPaneContainer() {const instance = typeof atom.workspace.getCenter === 'function' ? atom.workspace.getCenter().paneContainer : atom.workspace.paneContainer;const PaneContainer = instance.constructor;return new PaneContainer({ viewRegistry: atom.views, config: atom.config, applicationDelegate: atom.applicationDelegate, notificationManager: atom.notifications, | ||
deserializerManager: atom.deserializers }); | ||
} |
@@ -1,51 +0,62 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.default = | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.default = createPackage; | ||
/** | ||
* Create an Atom package from an Activation constructor. | ||
* | ||
* Atom packages are obstensibly singletons, however they contain `activate()` and `deactivate()` | ||
* lifecycle methods which can be called multiple times. There's no use-case (so far as we know) for | ||
* invoking any other package methods while a package is not activated. Therefore, it makes more | ||
* sense to build packages as instances, constructed when a package is activated and destroyed when | ||
* the package is deactivated. | ||
* | ||
* Atom uses a plain `require` to load the module, and not babel's `require` interop. So if | ||
* `createPackage` were used as `export default createPackage(..)`, then Atom wouldn't be | ||
* able to find any package methods because the ES Module transform would output | ||
* `module.exports.default = {..};`. To workaround this, the module's `module.exports` is passed | ||
* to `createPackage` so we can attach whatever properties to it. | ||
* | ||
* It was a conscious decision to use `createPackage(module.exports, Activation)` instead of | ||
* `module.exports = createPackage(Activation)`, to avoid code style misunderstandings wrt | ||
* CommonJS vs ES Modules. | ||
*/ | ||
function createPackage(moduleExports, Activation) { | ||
let activation = null; | ||
// Proxy method calls on the package to the activation object. | ||
for (const property of getPropertyList(Activation.prototype)) { | ||
if (typeof Activation.prototype[property] !== 'function') { | ||
continue; | ||
} | ||
if (property === 'constructor') { | ||
continue; | ||
} | ||
if (property === 'initialize') { | ||
throw new Error('Your activation class contains an "initialize" method, but that work should be done in the' + ' constructor.'); | ||
} | ||
createPackage; /** | ||
* Create an Atom package from an Activation constructor. | ||
* | ||
* Atom packages are obstensibly singletons, however they contain `activate()` and `deactivate()` | ||
* lifecycle methods which can be called multiple times. There's no use-case (so far as we know) for | ||
* invoking any other package methods while a package is not activated. Therefore, it makes more | ||
* sense to build packages as instances, constructed when a package is activated and destroyed when | ||
* the package is deactivated. | ||
* | ||
* Atom uses a plain `require` to load the module, and not babel's `require` interop. So if | ||
* `createPackage` were used as `export default createPackage(..)`, then Atom wouldn't be | ||
* able to find any package methods because the ES Module transform would output | ||
* `module.exports.default = {..};`. To workaround this, the module's `module.exports` is passed | ||
* to `createPackage` so we can attach whatever properties to it. | ||
* | ||
* It was a conscious decision to use `createPackage(module.exports, Activation)` instead of | ||
* `module.exports = createPackage(Activation)`, to avoid code style misunderstandings wrt | ||
* CommonJS vs ES Modules. | ||
*/function createPackage(moduleExports, Activation) {let activation = null; // Proxy method calls on the package to the activation object. | ||
for (const property of getPropertyList(Activation.prototype)) {if (typeof Activation.prototype[property] !== 'function') {continue;}if (property === 'constructor') {continue;}if (property === 'initialize') {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) { | ||
if (!(activation != null)) { | ||
throw new Error('Package not initialized'); | ||
} | ||
moduleExports[property] = function (...args) {if (!( | ||
activation != null)) {throw new Error('Package not initialized');} | ||
return activation[property](...args); | ||
@@ -56,9 +67,6 @@ }; | ||
/** | ||
* Calling `initialize()` creates a new instance. | ||
*/ | ||
moduleExports.initialize = initialState => { | ||
if (!(activation == null)) { | ||
throw new Error('Package already initialized'); | ||
} | ||
* Calling `initialize()` creates a new instance. | ||
*/ | ||
moduleExports.initialize = initialState => {if (!( | ||
activation == null)) {throw new Error('Package already initialized');} | ||
activation = new Activation(initialState); | ||
@@ -68,9 +76,6 @@ }; | ||
/** | ||
* The `deactivate()` method is special-cased to null our activation instance reference. | ||
*/ | ||
moduleExports.deactivate = () => { | ||
if (!(activation != null)) { | ||
throw new Error('Package not initialized'); | ||
} | ||
* The `deactivate()` method is special-cased to null our activation instance reference. | ||
*/ | ||
moduleExports.deactivate = () => {if (!( | ||
activation != null)) {throw new Error('Package not initialized');} | ||
if (typeof activation.dispose === 'function') { | ||
@@ -91,18 +96,8 @@ activation.dispose(); | ||
* @format | ||
*/ | ||
*/function getPrototypeChain(prototype) {let currentPrototype = prototype;const prototypes = [];while (currentPrototype != null) {prototypes.push(currentPrototype);currentPrototype = Object.getPrototypeOf(currentPrototype);}return prototypes;} | ||
function getPrototypeChain(prototype) { | ||
let currentPrototype = prototype; | ||
const prototypes = []; | ||
while (currentPrototype != null) { | ||
prototypes.push(currentPrototype); | ||
currentPrototype = Object.getPrototypeOf(currentPrototype); | ||
} | ||
return prototypes; | ||
} | ||
/** | ||
* List the properties (including inherited ones) of the provided prototype, excluding the ones | ||
* inherited from `Object`. | ||
*/ | ||
* List the properties (including inherited ones) of the provided prototype, excluding the ones | ||
* inherited from `Object`. | ||
*/ | ||
function getPropertyList(prototype) { | ||
@@ -109,0 +104,0 @@ const properties = []; |
176
debounced.js
@@ -1,100 +0,110 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports. | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.observeActivePaneItemDebounced = observeActivePaneItemDebounced; | ||
exports.observeActiveEditorsDebounced = observeActiveEditorsDebounced; | ||
exports.editorChangesDebounced = editorChangesDebounced; | ||
exports.editorScrollTopDebounced = editorScrollTopDebounced; | ||
exports.observeTextEditorsPositions = observeTextEditorsPositions; | ||
var _observable; | ||
function _load_observable() { | ||
return _observable = require('nuclide-commons/observable'); | ||
} | ||
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'); | ||
} | ||
/** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ | ||
/** | ||
* Often, we may want to respond to Atom events, but only after a buffer period | ||
* of no change. | ||
* For example, Atom provides Workspace::onDidChangeActivePaneItem, but we may | ||
* want to know not when the active pane item has changed, buth when it has | ||
* stopped changing. | ||
* This file provides methods to do this. | ||
*/ | ||
const DEFAULT_PANE_DEBOUNCE_INTERVAL_MS = 100; | ||
const DEFAULT_EDITOR_DEBOUNCE_INTERVAL_MS = 300; | ||
const DEFAULT_POSITION_DEBOUNCE_INTERVAL_MS = 300; | ||
function observeActivePaneItemDebounced(debounceInterval = DEFAULT_PANE_DEBOUNCE_INTERVAL_MS) { | ||
return (0, (_event || _load_event()).observableFromSubscribeFunction)(callback => { | ||
if (atom.workspace.getCenter != null) { | ||
return atom.workspace.getCenter().observeActivePaneItem(callback); | ||
} | ||
return atom.workspace.observeActivePaneItem(callback); | ||
}).let((0, (_observable || _load_observable()).fastDebounce)(debounceInterval)); | ||
} | ||
function observeActiveEditorsDebounced(debounceInterval = DEFAULT_PANE_DEBOUNCE_INTERVAL_MS) { | ||
return observeActivePaneItemDebounced(debounceInterval).map(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; | ||
} | ||
return null; | ||
}); | ||
} | ||
function editorChangesDebounced(editor, debounceInterval = DEFAULT_EDITOR_DEBOUNCE_INTERVAL_MS) { | ||
return (0, (_event || _load_event()).observableFromSubscribeFunction)(callback => editor.getBuffer().onDidChangeText(() => callback())) | ||
// Debounce manually rather than using editor.onDidStopChanging so that the debounce time is | ||
// configurable. | ||
.let((0, (_observable || _load_observable()).fastDebounce)(debounceInterval)); | ||
} | ||
function editorScrollTopDebounced(editor, debounceInterval = DEFAULT_EDITOR_DEBOUNCE_INTERVAL_MS) { | ||
return (0, (_event || _load_event()).observableFromSubscribeFunction)(callback => atom.views.getView(editor).onDidChangeScrollTop(callback)).let((0, (_observable || _load_observable()).fastDebounce)(debounceInterval)); | ||
} | ||
// Yields null when the current pane is not an editor, | ||
observeActivePaneItemDebounced = observeActivePaneItemDebounced;exports. | ||
observeActiveEditorsDebounced = observeActiveEditorsDebounced;exports. | ||
editorChangesDebounced = editorChangesDebounced;exports. | ||
editorScrollTopDebounced = editorScrollTopDebounced;exports. | ||
observeTextEditorsPositions = observeTextEditorsPositions;var _observable;function _load_observable() {return _observable = require('nuclide-commons/observable');}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');} /** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ /** | ||
* Often, we may want to respond to Atom events, but only after a buffer period | ||
* of no change. | ||
* For example, Atom provides Workspace::onDidChangeActivePaneItem, but we may | ||
* want to know not when the active pane item has changed, buth when it has | ||
* stopped changing. | ||
* This file provides methods to do this. | ||
*/const DEFAULT_PANE_DEBOUNCE_INTERVAL_MS = 100;const DEFAULT_EDITOR_DEBOUNCE_INTERVAL_MS = 300;const DEFAULT_POSITION_DEBOUNCE_INTERVAL_MS = 300;function observeActivePaneItemDebounced(debounceInterval = DEFAULT_PANE_DEBOUNCE_INTERVAL_MS) {return (0, (_event || _load_event()).observableFromSubscribeFunction)(callback => {if (atom.workspace.getCenter != null) {return atom.workspace.getCenter().observeActivePaneItem(callback);}return atom.workspace.observeActivePaneItem(callback);}).let((0, (_observable || _load_observable()).fastDebounce)(debounceInterval));}function observeActiveEditorsDebounced(debounceInterval = DEFAULT_PANE_DEBOUNCE_INTERVAL_MS) {return observeActivePaneItemDebounced(debounceInterval).map(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;}return null;});}function editorChangesDebounced(editor, debounceInterval = DEFAULT_EDITOR_DEBOUNCE_INTERVAL_MS) {return (0, (_event || _load_event()).observableFromSubscribeFunction)(callback => editor.getBuffer().onDidChangeText(() => callback())) // Debounce manually rather than using editor.onDidStopChanging so that the debounce time is | ||
// configurable. | ||
.let((0, (_observable || _load_observable()).fastDebounce)(debounceInterval));}function editorScrollTopDebounced(editor, debounceInterval = DEFAULT_EDITOR_DEBOUNCE_INTERVAL_MS) {return (0, (_event || _load_event()).observableFromSubscribeFunction)(callback => atom.views.getView(editor).onDidChangeScrollTop(callback)).let((0, (_observable || _load_observable()).fastDebounce)(debounceInterval));} // Yields null when the current pane is not an editor, | ||
// otherwise yields events on each move of the primary cursor within any Editor. | ||
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).let((0, (_observable || _load_observable()).fastDebounce)(positionDebounceInterval)).map(position => { | ||
if (!(editor != null)) { | ||
throw new Error('Invariant violation: "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).let((0, (_observable || _load_observable()).fastDebounce)(positionDebounceInterval)).map(position => {if (!(editor != null)) {throw new Error('Invariant violation: "editor != null"');}return { editor, position };});});} |
@@ -1,30 +0,27 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports. | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.getDebuggerService = getDebuggerService; | ||
var _consumeFirstProvider; | ||
function _load_consumeFirstProvider() { | ||
return _consumeFirstProvider = _interopRequireDefault(require('./consumeFirstProvider')); | ||
} | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
/** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ | ||
function getDebuggerService() { | ||
return (0, (_consumeFirstProvider || _load_consumeFirstProvider()).default)('debugger.remote'); | ||
} | ||
getDebuggerService = getDebuggerService;var _consumeFirstProvider;function _load_consumeFirstProvider() {return _consumeFirstProvider = _interopRequireDefault(require('./consumeFirstProvider'));}function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} /** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/function getDebuggerService() {return (0, (_consumeFirstProvider || _load_consumeFirstProvider()).default)('debugger.remote');} |
@@ -1,27 +0,23 @@ | ||
"use strict"; | ||
"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports. | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.destroyItemWhere = destroyItemWhere; | ||
/** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ | ||
function destroyItemWhere(predicate) { | ||
atom.workspace.getPanes().forEach(pane => { | ||
pane.getItems().forEach(item => { | ||
if (predicate(item)) { | ||
pane.destroyItem(item, true); | ||
} | ||
}); | ||
}); | ||
} | ||
destroyItemWhere = destroyItemWhere; /** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/function destroyItemWhere(predicate) {atom.workspace.getPanes().forEach(pane => {pane.getItems().forEach(item => {if (predicate(item)) {pane.destroyItem(item, true);}});});} |
@@ -1,30 +0,25 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.default = | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.default = dockForLocation; | ||
/** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ | ||
// Return the dock for a pane if the pane is in a dock (i.e. not in the center.) | ||
function dockForLocation(location) { | ||
switch (location) { | ||
case 'bottom': | ||
return atom.workspace.getBottomDock(); | ||
case 'left': | ||
return atom.workspace.getLeftDock(); | ||
case 'right': | ||
return atom.workspace.getRightDock(); | ||
} | ||
return null; | ||
} | ||
dockForLocation; /** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ // Return the dock for a pane if the pane is in a dock (i.e. not in the center.) | ||
function dockForLocation(location) {switch (location) {case 'bottom':return atom.workspace.getBottomDock();case 'left':return atom.workspace.getLeftDock();case 'right':return atom.workspace.getRightDock();}return null;} |
@@ -1,44 +0,36 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true }); | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js'); | ||
/** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ | ||
/** | ||
* A wrapper over Atom's config functions for use with FeatureLoader. | ||
* Each individual loaded package's config is a subconfig of the root package. | ||
*/ | ||
let packageName = null; | ||
/** | ||
* Sets the root package name. | ||
* This gets automatically called from FeatureLoader. | ||
*/ | ||
function setPackageName(name) { | ||
packageName = name; | ||
} | ||
function getPackageName() { | ||
if (!(packageName != null)) { | ||
throw new Error('No package name available'); | ||
} | ||
return packageName; | ||
} | ||
var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js'); /** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ /** | ||
* A wrapper over Atom's config functions for use with FeatureLoader. | ||
* Each individual loaded package's config is a subconfig of the root package. | ||
*/let packageName = null; /** | ||
* Sets the root package name. | ||
* This gets automatically called from FeatureLoader. | ||
*/function setPackageName(name) {packageName = name;}function getPackageName() {if (!(packageName != null)) {throw new Error('No package name available');}return packageName;} | ||
function formatKeyPath(keyPath) { | ||
@@ -52,20 +44,38 @@ if (packageName == null) { | ||
/* | ||
* Returns the value of a setting for a Nuclide feature key. Takes and returns the same types as | ||
* `atom.config.get` exception `keyPath` is not optional. To get the entire config object, use | ||
* `atom.config.get`. | ||
* | ||
* Note: This is intentionally typed as mixed, this way each call site has to | ||
* first cast it as any and it is obvious that this is an area that is not safe | ||
* and flow will not proceed if the callsite doesn't do it. | ||
* | ||
* Example: | ||
* const config: MyConfigType = (featureConfig.get('config-name'): any); | ||
*/ | ||
function get(keyPath, options) { | ||
* Returns the value of a setting for a Nuclide feature key. Takes and returns the same types as | ||
* `atom.config.get` exception `keyPath` is not optional. To get the entire config object, use | ||
* `atom.config.get`. | ||
* | ||
* Note: This is intentionally typed as mixed, this way each call site has to | ||
* first cast it as any and it is obvious that this is an area that is not safe | ||
* and flow will not proceed if the callsite doesn't do it. | ||
* | ||
* Example: | ||
* const config: MyConfigType = (featureConfig.get('config-name'): any); | ||
*/ | ||
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(keyPath, defaults, options) { | ||
function getWithDefaults( | ||
keyPath, | ||
defaults, | ||
options) | ||
{ | ||
const current = get(keyPath, options); | ||
@@ -76,5 +86,5 @@ return current == null ? defaults : current; | ||
/* | ||
* Gets the schema of a setting for a Nuclide feature key. Takes and returns the same types as | ||
* `atom.config.getSchema`. | ||
*/ | ||
* Gets the schema of a setting for a Nuclide feature key. Takes and returns the same types as | ||
* `atom.config.getSchema`. | ||
*/ | ||
function getSchema(keyPath) { | ||
@@ -85,7 +95,10 @@ return atom.config.getSchema(formatKeyPath(keyPath)); | ||
/* | ||
* Similar to `atom.config.observe` except arguments are required, and options cannot be given. | ||
* | ||
* To observe changes on the entire config, use `atom.config.observe`. | ||
*/ | ||
function observe(keyPath, callback) { | ||
* Similar to `atom.config.observe` except arguments are required, and options cannot be given. | ||
* | ||
* To observe changes on the entire config, use `atom.config.observe`. | ||
*/ | ||
function observe( | ||
keyPath, | ||
callback) | ||
{ | ||
return atom.config.observe(formatKeyPath(keyPath), callback); | ||
@@ -95,5 +108,5 @@ } | ||
/* | ||
* Behaves similarly to the `observe` function, but returns a stream of values, rather | ||
* then receiving a callback. | ||
*/ | ||
* Behaves similarly to the `observe` function, but returns a stream of values, rather | ||
* then receiving a callback. | ||
*/ | ||
function observeAsStream(keyPath) { | ||
@@ -107,37 +120,66 @@ return _rxjsBundlesRxMinJs.Observable.create(observer => { | ||
/* | ||
* Takes and returns the same types as `atom.config.onDidChange` except `keyPath` is not optional. | ||
* To listen to changes on all key paths, use `atom.config.onDidChange`. | ||
*/ | ||
function onDidChange(keyPath, optionsOrCallback, callback) { | ||
return atom.config.onDidChange(formatKeyPath(keyPath), ...Array.prototype.slice.call(arguments, 1)); | ||
* Takes and returns the same types as `atom.config.onDidChange` except `keyPath` is not optional. | ||
* To listen to changes on all key paths, use `atom.config.onDidChange`. | ||
*/ | ||
function onDidChange( | ||
keyPath, | ||
optionsOrCallback, | ||
callback) | ||
{ | ||
return atom.config.onDidChange( | ||
formatKeyPath(keyPath), | ||
...Array.prototype.slice.call(arguments, 1)); | ||
} | ||
/* | ||
* Sets the value of a setting for a Nuclide feature key. Takes and returns the same types as | ||
* `atom.config.set`. | ||
*/ | ||
function set(keyPath, value, options) { | ||
return atom.config.set(formatKeyPath(keyPath), ...Array.prototype.slice.call(arguments, 1)); | ||
* Sets the value of a setting for a Nuclide feature key. Takes and returns the same types as | ||
* `atom.config.set`. | ||
*/ | ||
function set( | ||
keyPath, | ||
value, | ||
options) | ||
{ | ||
return atom.config.set( | ||
formatKeyPath(keyPath), | ||
...Array.prototype.slice.call(arguments, 1)); | ||
} | ||
/* | ||
* Sets the schema of a setting for a Nuclide feature key. Takes and returns the same types as | ||
* `atom.config.setSchema`. | ||
*/ | ||
* Sets the schema of a setting for a Nuclide feature key. Takes and returns the same types as | ||
* `atom.config.setSchema`. | ||
*/ | ||
function setSchema(keyPath, schema) { | ||
return atom.config.setSchema(formatKeyPath(keyPath), ...Array.prototype.slice.call(arguments, 1)); | ||
return atom.config.setSchema( | ||
formatKeyPath(keyPath), | ||
...Array.prototype.slice.call(arguments, 1)); | ||
} | ||
/* | ||
* Restores a setting for a Nuclide feature key to its default value. Takes and returns the same | ||
* types as `atom.config.set`. | ||
*/ | ||
function unset(keyPath, options) { | ||
return atom.config.unset(formatKeyPath(keyPath), ...Array.prototype.slice.call(arguments, 1)); | ||
* Restores a setting for a Nuclide feature key to its default value. Takes and returns the same | ||
* types as `atom.config.set`. | ||
*/ | ||
function unset( | ||
keyPath, | ||
options) | ||
{ | ||
return atom.config.unset( | ||
formatKeyPath(keyPath), | ||
...Array.prototype.slice.call(arguments, 1)); | ||
} | ||
/** | ||
* Returns `true` if the feature with the given name is disabled either directly or because the | ||
* container package itself is disabled. | ||
*/ | ||
* Returns `true` if the feature with the given name is disabled either directly or because the | ||
* container package itself is disabled. | ||
*/ | ||
function isFeatureDisabled(name) { | ||
@@ -147,6 +189,9 @@ if (packageName == null) { | ||
} | ||
return atom.packages.isPackageDisabled(packageName) || !atom.config.get(`${packageName}.use.${name}`); | ||
} | ||
return ( | ||
atom.packages.isPackageDisabled(packageName) || | ||
!atom.config.get(`${packageName}.use.${name}`)); | ||
exports.default = { | ||
}exports.default = | ||
{ | ||
formatKeyPath, | ||
@@ -164,3 +209,2 @@ setPackageName, | ||
unset, | ||
isFeatureDisabled | ||
}; | ||
isFeatureDisabled }; |
@@ -1,41 +0,48 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });var _idx; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
var _idx; | ||
function _load_idx() { | ||
return _idx = _interopRequireDefault(require('idx')); | ||
} | ||
var _UniversalDisposable; | ||
function _load_UniversalDisposable() { | ||
return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable')); | ||
} | ||
var _nullthrows; | ||
function _load_nullthrows() { | ||
return _nullthrows = _interopRequireDefault(require('nullthrows')); | ||
} | ||
var _featureConfig; | ||
function _load_featureConfig() { | ||
return _featureConfig = _interopRequireDefault(require('./feature-config')); | ||
} | ||
var _path2 = _interopRequireDefault(require('path')); | ||
var _collection; | ||
function _load_collection() { | ||
return _collection = require('nuclide-commons/collection'); | ||
} | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _load_idx() {return _idx = _interopRequireDefault(require('idx'));}var _UniversalDisposable; | ||
function _load_UniversalDisposable() {return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable'));}var _nullthrows; | ||
function _load_nullthrows() {return _nullthrows = _interopRequireDefault(require('nullthrows'));}var _featureConfig; | ||
function _load_featureConfig() {return _featureConfig = _interopRequireDefault(require('./feature-config'));} | ||
var _path2 = _interopRequireDefault(require('path'));var _collection; | ||
function _load_collection() {return _collection = require('nuclide-commons/collection');}function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} | ||
const ALWAYS_ENABLED = 'always'; // eslint-disable-line rulesdir/prefer-nuclide-uri | ||
@@ -52,17 +59,10 @@ /** | ||
* @format | ||
*/ | ||
*/ /* global localStorage */const NEVER_ENABLED = 'never';const DEFAULT = 'default';const { devMode } = atom.getLoadSettings();class FeatureLoader { | ||
/* global localStorage */ | ||
const NEVER_ENABLED = 'never'; | ||
const DEFAULT = 'default'; | ||
const { devMode } = atom.getLoadSettings(); | ||
class FeatureLoader { | ||
constructor({ features, path: _path, featureGroups }) { | ||
this._featureGroupMap = new (_collection || _load_collection()).MultiMap(); | ||
this._currentPackageState = new Set(); | ||
constructor({ features, path: _path, featureGroups }) {this._featureGroupMap = new (_collection || _load_collection()).MultiMap();this._currentPackageState = new Set(); | ||
this._path = _path; | ||
@@ -82,12 +82,10 @@ this._features = features; | ||
collapsed: true, | ||
properties: {} | ||
} | ||
}; | ||
properties: {} } }; | ||
} | ||
// Build the config. Should occur with root package's load | ||
load() { | ||
if (!!this._loadDisposable.disposed) { | ||
throw new Error('Invariant violation: "!this._loadDisposable.disposed"'); | ||
} | ||
load() {if (! | ||
!this._loadDisposable.disposed) {throw new Error('Invariant violation: "!this._loadDisposable.disposed"');} | ||
@@ -104,8 +102,8 @@ // 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() {} | ||
})); | ||
@@ -128,12 +126,19 @@ // | ||
const setting = { | ||
title: featurePkg.displayName == null ? `Enable the "${name}" feature` : `Enable ${featurePkg.displayName}`, | ||
title: | ||
featurePkg.displayName == null ? | ||
`Enable the "${name}" feature` : | ||
`Enable ${featurePkg.displayName}`, | ||
description: featurePkg.description || '', | ||
type: 'string', | ||
enum: [{ value: ALWAYS_ENABLED, description: 'Always enabled' }, { value: NEVER_ENABLED, description: 'Never enabled' }, { | ||
enum: [ | ||
{ value: ALWAYS_ENABLED, description: 'Always enabled' }, | ||
{ value: NEVER_ENABLED, description: 'Never enabled' }, | ||
{ | ||
value: DEFAULT, | ||
description: 'Only when in an enabled package group' | ||
}], | ||
default: getFeatureDefaultValue(feature) | ||
}; | ||
description: 'Only when in an enabled package group' }], | ||
default: getFeatureDefaultValue(feature) }; | ||
if (devMode) { | ||
@@ -153,3 +158,5 @@ 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; | ||
@@ -162,8 +169,9 @@ if (featurePkgConfig) { | ||
collapsed: true, | ||
properties: {} | ||
}; | ||
properties: {} }; | ||
Object.keys(featurePkgConfig).forEach(key => { | ||
this._config[name].properties[key] = Object.assign({}, featurePkgConfig[key], { | ||
title: featurePkgConfig[key].title || key | ||
}); | ||
this._config[name].properties[key] = Object.assign({}, | ||
featurePkgConfig[key], { | ||
title: featurePkgConfig[key].title || key }); | ||
}); | ||
@@ -192,8 +200,5 @@ } | ||
} | ||
}); | ||
});if (!( | ||
if (!(initialLoadDisposable != null)) { | ||
throw new Error('Invariant violation: "initialLoadDisposable != null"'); | ||
} | ||
initialLoadDisposable != null)) {throw new Error('Invariant violation: "initialLoadDisposable != null"');} | ||
this._loadDisposable.remove(initialLoadDisposable); | ||
@@ -206,20 +211,14 @@ initialLoadDisposable.dispose(); | ||
activate() { | ||
if (!(this._activationDisposable == null)) { | ||
throw new Error('Invariant violation: "this._activationDisposable == null"'); | ||
} | ||
activate() {if (!( | ||
this._activationDisposable == null)) {throw new Error('Invariant violation: "this._activationDisposable == null"');} | ||
const rootPackage = atom.packages.getLoadedPackage(this._pkgName);if (!( | ||
rootPackage != null)) {throw new Error('Invariant violation: "rootPackage != null"');} | ||
const rootPackage = atom.packages.getLoadedPackage(this._pkgName); | ||
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()); | ||
// Hack time!! Atom's repository APIs are synchronous. Any package that tries to use them before | ||
@@ -231,3 +230,5 @@ // we've had a chance to provide our implementation are going to get wrong answers. The correct | ||
// activation of the features that provide this service. | ||
const originalOrder = new Map(this._features.map((feature, i) => [feature, i])); | ||
const originalOrder = new Map( | ||
this._features.map((feature, i) => [feature, i])); | ||
this._features.sort((a, b) => { | ||
@@ -250,4 +251,7 @@ const aIsRepoProvider = packageIsRepositoryProvider(a.pkg); | ||
// TODO: When enough users have migrated, this should be removed along with the enum migration. | ||
atom.config.set(this.useKeyPathForFeature(feature), atom.config.get(this.useKeyPathForFeature(feature))); | ||
atom.config.set( | ||
this.useKeyPathForFeature(feature), | ||
atom.config.get(this.useKeyPathForFeature(feature))); | ||
if (this.shouldEnable(feature)) { | ||
@@ -259,4 +263,11 @@ atom.packages.activatePackage(feature.path); | ||
// Watch the config to manage toggling features | ||
this._activationDisposable = new (_UniversalDisposable || _load_UniversalDisposable()).default(atom.config.onDidChange(this.useKeyPath(), event => this.updateActiveFeatures()), atom.config.onDidChange(this.useKeyPathForFeatureGroup(), event => this.updateActiveFeatures())); | ||
this._activationDisposable = new (_UniversalDisposable || _load_UniversalDisposable()).default( | ||
atom.config.onDidChange(this.useKeyPath(), event => | ||
this.updateActiveFeatures()), | ||
atom.config.onDidChange(this.useKeyPathForFeatureGroup(), event => | ||
this.updateActiveFeatures())); | ||
this.updateActiveFeatures(); | ||
@@ -291,7 +302,7 @@ } | ||
deactivate() { | ||
if (!(this._activationDisposable && !this._activationDisposable.disposed)) { | ||
throw new Error('Invariant violation: "this._activationDisposable && !this._activationDisposable.disposed"'); | ||
} | ||
deactivate() {if (!( | ||
this._activationDisposable && !this._activationDisposable.disposed)) {throw new Error('Invariant violation: "this._activationDisposable && !this._activationDisposable.disposed"');} | ||
this._features.forEach(feature => { | ||
@@ -301,9 +312,5 @@ // Deactivate the package, but don't serialize. That needs to be done in a separate phase so that | ||
safeDeactivate(feature, true); | ||
}); | ||
});if (! | ||
if (!this._activationDisposable) { | ||
throw new Error('Invariant violation: "this._activationDisposable"'); | ||
} // reasserting for flow | ||
this._activationDisposable) {throw new Error('Invariant violation: "this._activationDisposable"');} // reasserting for flow | ||
this._activationDisposable.dispose(); | ||
@@ -313,3 +320,6 @@ this._activationDisposable = null; | ||
getDesiredState(featureState, featureGroupState) { | ||
getDesiredState( | ||
featureState, | ||
featureGroupState) | ||
{ | ||
// Figure out which features should be enabled: | ||
@@ -320,3 +330,7 @@ // * Add all packages in nuclide.use | ||
if (featureGroupState != null) { | ||
groupedPackages = (0, (_collection || _load_collection()).setUnion)(...featureGroupState.map(featureGroup => this._featureGroupMap.get(featureGroup))); | ||
groupedPackages = (0, (_collection || _load_collection()).setUnion)( | ||
...featureGroupState.map(featureGroup => | ||
this._featureGroupMap.get(featureGroup))); | ||
} else { | ||
@@ -329,6 +343,12 @@ // If featuregroups is empty or undefined, assume all features should be enabled. | ||
// If a feature is "default", it should be on if and only if a feature-group includes it. | ||
return new Set(this._features.filter(feature => { | ||
return new Set( | ||
this._features.filter(feature => { | ||
const state = featureState[packageNameFromPath(feature.path)]; | ||
return state === ALWAYS_ENABLED || groupedPackages.has(feature) && state === DEFAULT || state === true; | ||
return ( | ||
state === ALWAYS_ENABLED || | ||
groupedPackages.has(feature) && state === DEFAULT || | ||
state === true); | ||
})); | ||
} | ||
@@ -338,6 +358,6 @@ | ||
/* | ||
* Construct a map from feature name to feature. The _featureGroupMap | ||
* must contain the true feature objects, but featureGroups.cson only has | ||
* the feature names. | ||
*/ | ||
* Construct a map from feature name to feature. The _featureGroupMap | ||
* must contain the true feature objects, but featureGroups.cson only has | ||
* the feature names. | ||
*/ | ||
const featureMap = new Map(); | ||
@@ -350,3 +370,5 @@ this._features.forEach(feature => { | ||
if (Array.isArray(this._featureGroups[key])) { | ||
const featuresForKey = this._featureGroups[key].map(featureName => featureMap.get(featureName)).filter(Boolean); | ||
const featuresForKey = this._featureGroups[key]. | ||
map(featureName => featureMap.get(featureName)). | ||
filter(Boolean); | ||
if (featuresForKey != null) { | ||
@@ -407,4 +429,4 @@ this._featureGroupMap.set(key, featuresForKey); | ||
// If this is the case, set to false if it begins with sample- and true otherwise. | ||
return !name.startsWith('sample-'); | ||
} | ||
return !name.startsWith('sample-');} | ||
} | ||
@@ -421,3 +443,6 @@ | ||
getValueForFeatureToEnumMigration(currentState, feature) { | ||
getValueForFeatureToEnumMigration( | ||
currentState, | ||
feature) | ||
{ | ||
const name = packageNameFromPath(feature.path); | ||
@@ -432,16 +457,15 @@ | ||
case NEVER_ENABLED: | ||
case DEFAULT: | ||
if (!(typeof currentState === 'string')) { | ||
throw new Error('Invariant violation: "typeof currentState === \'string\'"'); | ||
} | ||
case DEFAULT:if (!( | ||
typeof currentState === 'string')) {throw new Error('Invariant violation: "typeof currentState === \'string\'"');} | ||
return currentState; | ||
default: | ||
return getFeatureDefaultValue(feature); | ||
} | ||
} | ||
} | ||
return getFeatureDefaultValue(feature);} | ||
exports.default = FeatureLoader; | ||
function safeDeactivate(feature, suppressSerialization = false) { | ||
}}exports.default = FeatureLoader; | ||
function safeDeactivate( | ||
feature, | ||
suppressSerialization = false) | ||
{ | ||
const name = packageNameFromPath(feature.path); | ||
@@ -484,6 +508,4 @@ try { | ||
function packageIsRepositoryProvider(pkg) { | ||
var _ref, _ref2; | ||
function packageIsRepositoryProvider(pkg) {var _ref, _ref2; | ||
return Boolean((_ref = pkg) != null ? (_ref2 = _ref.providedServices) != null ? _ref2['atom.repository-provider'] : _ref2 : _ref); | ||
} |
@@ -1,8 +0,21 @@ | ||
"use strict"; | ||
"use strict";Object.defineProperty(exports, "__esModule", { value: true }); | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
class FocusBoomerang { | ||
recordFocus() { | ||
@@ -15,4 +28,4 @@ if (this._focus != null) { | ||
node: document.activeElement, | ||
pane: atom.workspace.getActivePane() | ||
}; | ||
pane: atom.workspace.getActivePane() }; | ||
} | ||
@@ -32,14 +45,12 @@ | ||
} | ||
} | ||
} | ||
exports.default = FocusBoomerang; /** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ | ||
}}exports.default = FocusBoomerang; /** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ |
@@ -1,35 +0,36 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.default = | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.default = getFragmentGrammar; | ||
/** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ | ||
/** | ||
* Some grammars should use a specialized grammar for code fragments | ||
* (namely PHP, since it's wildly different depending on the presence of a <?php opening). | ||
*/ | ||
const FRAGMENT_GRAMMARS = Object.freeze({ | ||
'text.html.hack': 'source.hackfragment', | ||
'text.html.php': 'source.hackfragment' | ||
}); | ||
function getFragmentGrammar(grammar) { | ||
if (FRAGMENT_GRAMMARS.hasOwnProperty(grammar.scopeName)) { | ||
const fragmentGrammar = FRAGMENT_GRAMMARS[grammar.scopeName]; | ||
return atom.grammars.grammarForScopeName(fragmentGrammar) || grammar; | ||
} | ||
return grammar; | ||
} | ||
getFragmentGrammar; /** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ /** | ||
* Some grammars should use a specialized grammar for code fragments | ||
* (namely PHP, since it's wildly different depending on the presence of a <?php opening). | ||
*/const FRAGMENT_GRAMMARS = Object.freeze({ 'text.html.hack': 'source.hackfragment', 'text.html.php': 'source.hackfragment' });function getFragmentGrammar(grammar) {if (FRAGMENT_GRAMMARS.hasOwnProperty(grammar.scopeName)) {const fragmentGrammar = FRAGMENT_GRAMMARS[grammar.scopeName];return atom.grammars.grammarForScopeName(fragmentGrammar) || grammar;}return grammar;} |
@@ -1,44 +0,64 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.goToLocation = undefined;var _asyncToGenerator = _interopRequireDefault(require('async-to-generator')); | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.goToLocation = undefined; | ||
var _asyncToGenerator = _interopRequireDefault(require('async-to-generator')); | ||
/** | ||
* Opens the given file. | ||
* | ||
* Optionally include a line and column to navigate to. If a line is given, by default it will | ||
* center it in the opened text editor. | ||
* | ||
* This should be preferred over `atom.workspace.open()` in typical cases. The motivations are: | ||
* - We call `atom.workspace.open()` with the `searchAllPanes` option. This looks in other panes for | ||
* the current file, rather just opening a new copy in the current pane. People often forget this | ||
* option which typically leads to a subpar experience for people who use multiple panes. | ||
* - When moving around in the current file, `goToLocation` explicitly publishes events that the nav | ||
* stack uses. | ||
* | ||
* Currently, `atom.workspace.open()` should be used only in these cases: | ||
* - When the URI to open is not a file URI. For example, if we want to open some tool like find | ||
* references in a pane. | ||
* - When we want to open an untitled file (providing no file argument). Currently, goToLocation | ||
* requires a file to open. | ||
* - When we want to open a file as a pending pane item. Currently goToLocation cannot do this. | ||
* | ||
* In these cases, you may disable the lint rule against `atom.workspace.open` by adding the | ||
* following comment above its use: | ||
* // eslint-disable-next-line rulesdir/atom-apis | ||
*/ | ||
let goToLocation = exports.goToLocation = (() => { | ||
var _ref8 = (0, _asyncToGenerator.default)(function* (file, options) { | ||
var _ref, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7; | ||
const center_ = (_ref = options) != null ? _ref.center : _ref; | ||
const center = center_ == null ? true : center_; | ||
const moveCursor_ = (_ref2 = options) != null ? _ref2.moveCursor : _ref2; | ||
const moveCursor = moveCursor_ == null ? true : moveCursor_; | ||
const activatePane_ = (_ref3 = options) != null ? _ref3.activatePane : _ref3; | ||
const activatePane = activatePane_ == null ? true : activatePane_; | ||
* Opens the given file. | ||
* | ||
* Optionally include a line and column to navigate to. If a line is given, by default it will | ||
* center it in the opened text editor. | ||
* | ||
* This should be preferred over `atom.workspace.open()` in typical cases. The motivations are: | ||
* - We call `atom.workspace.open()` with the `searchAllPanes` option. This looks in other panes for | ||
* the current file, rather just opening a new copy in the current pane. People often forget this | ||
* option which typically leads to a subpar experience for people who use multiple panes. | ||
* - When moving around in the current file, `goToLocation` explicitly publishes events that the nav | ||
* stack uses. | ||
* | ||
* Currently, `atom.workspace.open()` should be used only in these cases: | ||
* - When the URI to open is not a file URI. For example, if we want to open some tool like find | ||
* references in a pane. | ||
* - When we want to open an untitled file (providing no file argument). Currently, goToLocation | ||
* requires a file to open. | ||
* - When we want to open a file as a pending pane item. Currently goToLocation cannot do this. | ||
* | ||
* In these cases, you may disable the lint rule against `atom.workspace.open` by adding the | ||
* following comment above its use: | ||
* // eslint-disable-next-line rulesdir/atom-apis | ||
*/ /** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/let goToLocation = exports.goToLocation = (() => {var _ref8 = (0, _asyncToGenerator.default)(function* (file, options) {var _ref, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7;const center_ = (_ref = options) != null ? _ref.center : _ref;const center = center_ == null ? true : center_;const moveCursor_ = (_ref2 = options) != null ? _ref2.moveCursor : _ref2;const moveCursor = moveCursor_ == null ? true : moveCursor_;const activatePane_ = (_ref3 = options) != null ? _ref3.activatePane : _ref3;const activatePane = activatePane_ == null ? true : activatePane_; | ||
const activateItem = (_ref4 = options) != null ? _ref4.activateItem : _ref4; | ||
@@ -52,8 +72,4 @@ const line = (_ref5 = options) != null ? _ref5.line : _ref5; | ||
if (currentEditor != null && currentEditor.getPath() === file) { | ||
const paneContainer = atom.workspace.paneContainerForItem(currentEditor); | ||
if (!(paneContainer != null)) { | ||
throw new Error('Invariant violation: "paneContainer != null"'); | ||
} | ||
const paneContainer = atom.workspace.paneContainerForItem(currentEditor);if (!( | ||
paneContainer != null)) {throw new Error('Invariant violation: "paneContainer != null"');} | ||
if (activatePane) { | ||
@@ -67,8 +83,6 @@ paneContainer.activate(); | ||
center, | ||
moveCursor | ||
}); | ||
} else { | ||
if (!(column == null)) { | ||
throw new Error('goToLocation: Cannot specify just column'); | ||
} | ||
moveCursor }); | ||
} else {if (!( | ||
column == null)) {throw new Error('goToLocation: Cannot specify just column');} | ||
} | ||
@@ -85,5 +99,13 @@ return currentEditor; | ||
activateItem, | ||
pending | ||
}); | ||
pending }); | ||
// TODO(T28305560) Investigate offenders for this error | ||
if (editor == null) { | ||
const tmp = {}; | ||
Error.captureStackTrace(tmp); | ||
const error = Error(`atom.workspace.open returned null on ${file}`); | ||
(0, (_log4js || _load_log4js()).getLogger)('goToLocation').error(error); | ||
throw error; | ||
} | ||
if (center && line != null) { | ||
@@ -94,54 +116,37 @@ editor.scrollToBufferPosition([line, column], { center: true }); | ||
} | ||
}); | ||
});return function goToLocation(_x, _x2) {return _ref8.apply(this, arguments);};})();exports. | ||
return function goToLocation(_x, _x2) { | ||
return _ref8.apply(this, arguments); | ||
}; | ||
})(); /** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ | ||
exports.goToLocationInEditor = goToLocationInEditor; | ||
exports.observeNavigatingEditors = observeNavigatingEditors; | ||
var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js'); | ||
var _idx; | ||
function _load_idx() { | ||
return _idx = _interopRequireDefault(require('idx')); | ||
} | ||
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 | ||
function goToLocationInEditor(editor, options) { | ||
const center = options.center == null ? true : options.center; | ||
const moveCursor = options.moveCursor == null ? true : options.moveCursor; | ||
const { line, column } = options; | ||
if (moveCursor) { | ||
editor.setCursorBufferPosition([line, column]); | ||
} | ||
if (center) { | ||
editor.scrollToBufferPosition([line, column], { center: true }); | ||
} | ||
goToLocationSubject.next(editor); | ||
} | ||
function observeNavigatingEditors() { | ||
return goToLocationSubject; | ||
} | ||
goToLocationInEditor = goToLocationInEditor;exports. | ||
observeNavigatingEditors = observeNavigatingEditors;var _log4js;function _load_log4js() {return _log4js = require('log4js');}var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js');var _idx;function _load_idx() {return _idx = _interopRequireDefault(require('idx'));}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 | ||
function goToLocationInEditor(editor, options) {const center = options.center == null ? true : options.center;const moveCursor = options.moveCursor == null ? true : options.moveCursor;const { line, column } = options;if (moveCursor) {editor.setCursorBufferPosition([line, column]);}if (center) {editor.scrollToBufferPosition([line, column], { center: true });}goToLocationSubject.next(editor);}function observeNavigatingEditors() {return goToLocationSubject;} |
@@ -1,35 +0,37 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.default = | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.default = humanizePath; | ||
var _idx; | ||
function _load_idx() { | ||
return _idx = _interopRequireDefault(require('idx')); | ||
} | ||
var _nuclideUri; | ||
function _load_nuclideUri() { | ||
return _nuclideUri = _interopRequireDefault(require('nuclide-commons/nuclideUri')); | ||
} | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
/** | ||
* Format a path for display. After the path is humanized, it should no longer be treated like a | ||
* parsable, navigable path; it's just for display. | ||
* | ||
* Note that this (intentionally) provides different results based on the projects currently open in | ||
* Atom. If you have multiple directories open, the result will be prefixed with one of their names. | ||
* If you only have one, it won't. | ||
*/ | ||
function humanizePath(path, options) { | ||
var _ref, _ref2; | ||
const isDirectory = (_ref = options) != null ? _ref.isDirectory : _ref; | ||
const rootPaths = ((_ref2 = options) != null ? _ref2.rootPaths : _ref2) || atom.project.getDirectories().map(dir => dir.getPath()); | ||
humanizePath;var _idx;function _load_idx() {return _idx = _interopRequireDefault(require('idx'));}var _nuclideUri;function _load_nuclideUri() {return _nuclideUri = _interopRequireDefault(require('nuclide-commons/nuclideUri'));}function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} /** | ||
* Format a path for display. After the path is humanized, it should no longer be treated like a | ||
* parsable, navigable path; it's just for display. | ||
* | ||
* Note that this (intentionally) provides different results based on the projects currently open in | ||
* Atom. If you have multiple directories open, the result will be prefixed with one of their names. | ||
* If you only have one, it won't. | ||
*/function humanizePath(path, options) {var _ref, _ref2;const isDirectory = (_ref = options) != null ? _ref.isDirectory : _ref; | ||
const rootPaths = | ||
((_ref2 = options) != null ? _ref2.rootPaths : _ref2) || | ||
atom.project.getDirectories().map(dir => dir.getPath()); | ||
const normalized = normalizePath(path, isDirectory); | ||
@@ -66,7 +68,2 @@ let resolved; | ||
* @format | ||
*/ | ||
function normalizePath(path, isDirectory_) { | ||
const isDirectory = isDirectory_ == null ? (_nuclideUri || _load_nuclideUri()).default.endsWithSeparator(path) : isDirectory_; | ||
return isDirectory ? (_nuclideUri || _load_nuclideUri()).default.normalizeDir(path) : (_nuclideUri || _load_nuclideUri()).default.normalize(path); | ||
} | ||
*/function normalizePath(path, isDirectory_) {const isDirectory = isDirectory_ == null ? (_nuclideUri || _load_nuclideUri()).default.endsWithSeparator(path) : isDirectory_;return isDirectory ? (_nuclideUri || _load_nuclideUri()).default.normalizeDir(path) : (_nuclideUri || _load_nuclideUri()).default.normalize(path);} |
@@ -1,23 +0,25 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports. | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.bufferPositionForMouseEvent = bufferPositionForMouseEvent; | ||
function bufferPositionForMouseEvent(event, editor = null) { | ||
const _editor = editor || atom.workspace.getActiveTextEditor(); | ||
if (!(_editor != null)) { | ||
throw new Error('Invariant violation: "_editor != null"'); | ||
} | ||
const view = atom.views.getView(_editor); | ||
const component = view.component; | ||
if (!(component != null)) { | ||
throw new Error('Invariant violation: "component != null"'); | ||
} | ||
// Beware, screenPositionForMouseEvent is not a public api and may change in future versions. | ||
bufferPositionForMouseEvent = bufferPositionForMouseEvent;function bufferPositionForMouseEvent( | ||
event, | ||
editor = null) | ||
{ | ||
const _editor = editor || atom.workspace.getActiveTextEditor();if (!( | ||
_editor != null)) {throw new Error('Invariant violation: "_editor != null"');} | ||
const view = atom.views.getView(_editor); | ||
const component = view.component;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); | ||
@@ -24,0 +26,0 @@ return _editor.bufferPositionForScreenPosition(screenPosition); |
@@ -1,93 +0,85 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.default = | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.default = observePaneItemVisibility; | ||
exports.observeVisibleItems = observeVisibleItems; | ||
var _event; | ||
function _load_event() { | ||
return _event = require('nuclide-commons/event'); | ||
} | ||
var _memoizeUntilChanged; | ||
function _load_memoizeUntilChanged() { | ||
return _memoizeUntilChanged = _interopRequireDefault(require('nuclide-commons/memoizeUntilChanged')); | ||
} | ||
var _collection; | ||
function _load_collection() { | ||
return _collection = require('nuclide-commons/collection'); | ||
} | ||
var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js'); | ||
var _shallowequal; | ||
function _load_shallowequal() { | ||
return _shallowequal = _interopRequireDefault(require('shallowequal')); | ||
} | ||
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. | ||
function observePaneItemVisibility(item) { | ||
patchDocks(); | ||
const workspaceEl = atom.workspace.getElement(); | ||
return _rxjsBundlesRxMinJs.Observable.combineLatest( | ||
// atom.workspace.reset() (in tests) resets all the panes. | ||
// Pass in the workspace dom element to act as a cache-breaker. | ||
observeActiveItems(workspaceEl), observePaneContainerVisibilities(workspaceEl)).map(([activeItems, locationVisibilities]) => { | ||
// If it's not active, it's not visible. | ||
if (!activeItems.has(item)) { | ||
return false; | ||
} | ||
// If it's active, it's only visible if its container is. | ||
const paneContainer = atom.workspace.paneContainerForItem(item); | ||
return paneContainer == null ? false : locationVisibilities[paneContainer.getLocation()]; | ||
}).distinctUntilChanged(); | ||
} /** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ | ||
function observeVisibleItems() { | ||
patchDocks(); | ||
const workspaceEl = atom.workspace.getElement(); | ||
return _rxjsBundlesRxMinJs.Observable.combineLatest(observeActiveItems(workspaceEl), observePaneContainerVisibilities(workspaceEl)).map(([activeItems, locationVisibilities]) => { | ||
// If it's not active, it's not visible. | ||
observePaneItemVisibility;exports. | ||
observeVisibleItems = observeVisibleItems;var _event;function _load_event() {return _event = require('nuclide-commons/event');}var _memoizeUntilChanged;function _load_memoizeUntilChanged() {return _memoizeUntilChanged = _interopRequireDefault(require('nuclide-commons/memoizeUntilChanged'));}var _collection;function _load_collection() {return _collection = require('nuclide-commons/collection');}var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js');var _shallowequal;function _load_shallowequal() {return _shallowequal = _interopRequireDefault(require('shallowequal'));}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. | ||
function observePaneItemVisibility(item) {patchDocks();const workspaceEl = atom.workspace.getElement();return _rxjsBundlesRxMinJs.Observable.combineLatest( // atom.workspace.reset() (in tests) resets all the panes. | ||
// Pass in the workspace dom element to act as a cache-breaker. | ||
observeActiveItems(workspaceEl), observePaneContainerVisibilities(workspaceEl)).map(([activeItems, locationVisibilities]) => {// If it's not active, it's not visible. | ||
if (!activeItems.has(item)) {return false;} // If it's active, it's only visible if its container is. | ||
const paneContainer = atom.workspace.paneContainerForItem(item);return paneContainer == null ? false : locationVisibilities[paneContainer.getLocation()];}).distinctUntilChanged();} /** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/function observeVisibleItems() {patchDocks();const workspaceEl = atom.workspace.getElement();return _rxjsBundlesRxMinJs.Observable.combineLatest(observeActiveItems(workspaceEl), observePaneContainerVisibilities(workspaceEl)).map(([activeItems, locationVisibilities]) => {// If it's not active, it's not visible. | ||
// If it's active, it's only visible if its container is. | ||
return (0, (_collection || _load_collection()).setFilter)(activeItems, item => { | ||
const paneContainer = atom.workspace.paneContainerForItem(item); | ||
const location = paneContainer && paneContainer.getLocation(); | ||
return location ? Boolean(locationVisibilities[location]) : false; | ||
}); | ||
}); | ||
} | ||
const observeActiveItems = (0, (_memoizeUntilChanged || _load_memoizeUntilChanged()).default)(_cacheKey => { | ||
return (0, (_collection || _load_collection()).setFilter)(activeItems, item => {const paneContainer = atom.workspace.paneContainerForItem(item);const location = paneContainer && paneContainer.getLocation();return location ? Boolean(locationVisibilities[location]) : false;});});}const observeActiveItems = (0, (_memoizeUntilChanged || _load_memoizeUntilChanged()).default)(_cacheKey => { | ||
// An observable that emits `{pane, item}` whenever the active item of a pane changes. | ||
const itemActivations = _rxjsBundlesRxMinJs.Observable.merge(...atom.workspace.getPaneContainers().map(paneContainer => { | ||
const itemActivations = _rxjsBundlesRxMinJs.Observable.merge( | ||
...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 })); | ||
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 | ||
@@ -104,6 +96,10 @@ // every time; this is an optimization. | ||
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 => new Set(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 => new Set(map.values())). | ||
share()); | ||
}); | ||
@@ -114,6 +110,15 @@ | ||
const observePaneContainerVisibilities = (0, (_memoizeUntilChanged || _load_memoizeUntilChanged()).default)(_cacheKey => { | ||
const visibilitiesByDock = ['left', 'right', 'bottom'].map(loc => dockStateChanges.filter(({ location }) => location === loc).switchMap(({ location, visible }) => | ||
const visibilitiesByDock = ['left', 'right', 'bottom'].map(loc => | ||
dockStateChanges. | ||
filter(({ location }) => location === loc). | ||
switchMap( | ||
({ location, visible }) => | ||
// Delay the "false" values so they don't occur while the dock is being animated closed. | ||
visible ? _rxjsBundlesRxMinJs.Observable.of({ location, visible }) : _rxjsBundlesRxMinJs.Observable.of({ location, visible }).delay(300)).distinctUntilKeyChanged('visible')); | ||
visible ? | ||
_rxjsBundlesRxMinJs.Observable.of({ location, visible }) : | ||
_rxjsBundlesRxMinJs.Observable.of({ location, visible }).delay(300)). | ||
distinctUntilKeyChanged('visible')); | ||
const initialVisibilities = { | ||
@@ -124,9 +129,17 @@ // The center is always visible. | ||
right: atom.workspace.getRightDock().isVisible(), | ||
bottom: atom.workspace.getBottomDock().isVisible() | ||
}; | ||
bottom: atom.workspace.getBottomDock().isVisible() }; | ||
// Accumulate the dock visibilities. | ||
const visibilityStates = _rxjsBundlesRxMinJs.Observable.merge(...visibilitiesByDock).scan((acc, { location, visible }) => Object.assign({}, acc, { | ||
[location]: visible | ||
}), initialVisibilities).startWith(initialVisibilities).distinctUntilChanged((_shallowequal || _load_shallowequal()).default).publishReplay(1); | ||
const visibilityStates = _rxjsBundlesRxMinJs.Observable.merge(...visibilitiesByDock). | ||
scan( | ||
(acc, { location, visible }) => Object.assign({}, | ||
acc, { | ||
[location]: visible }), | ||
initialVisibilities). | ||
startWith(initialVisibilities). | ||
distinctUntilChanged((_shallowequal || _load_shallowequal()).default). | ||
publishReplay(1); | ||
visibilityStates.connect(); | ||
@@ -156,6 +169,6 @@ | ||
location: this.getLocation(), | ||
visible: newState.visible | ||
}); | ||
visible: newState.visible }); | ||
} | ||
}; | ||
} |
{ | ||
"name": "nuclide-commons-atom", | ||
"version": "0.7.0", | ||
"version": "0.7.1", | ||
"description": "Common Nuclide node modules (for use with Atom only).", | ||
@@ -19,3 +19,3 @@ "author": "NEEDS OWNER", | ||
"log4js": "1.1.1", | ||
"nuclide-commons": "0.7.0", | ||
"nuclide-commons": "0.7.1", | ||
"nullthrows": "1.0.0", | ||
@@ -22,0 +22,0 @@ "redux-logger": "3.0.6", |
@@ -1,38 +0,31 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports. | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.isPending = isPending; | ||
exports.observePendingStateEnd = observePendingStateEnd; | ||
var _event; | ||
function _load_event() { | ||
return _event = require('nuclide-commons/event'); | ||
} | ||
/** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ | ||
function isPending(paneItem) { | ||
const pane = atom.workspace.paneForItem(paneItem); | ||
return pane && pane.getPendingItem() === paneItem; | ||
} | ||
function observePendingStateEnd(paneItem) { | ||
if (!(typeof paneItem.onDidTerminatePendingState === 'function')) { | ||
throw new Error('paneItem must implement onDidTerminatePendingState method'); | ||
} | ||
return (0, (_event || _load_event()).observableFromSubscribeFunction)(paneItem.onDidTerminatePendingState.bind(paneItem)); | ||
} | ||
isPending = isPending;exports. | ||
observePendingStateEnd = observePendingStateEnd;var _event;function _load_event() {return _event = require('nuclide-commons/event');} /** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/function isPending(paneItem) {const pane = atom.workspace.paneForItem(paneItem);return pane && pane.getPendingItem() === paneItem;}function observePendingStateEnd(paneItem) {if (!(typeof paneItem.onDidTerminatePendingState === 'function')) {throw new Error('paneItem must implement onDidTerminatePendingState method');}return (0, (_event || _load_event()).observableFromSubscribeFunction)(paneItem.onDidTerminatePendingState.bind(paneItem));} |
@@ -1,10 +0,24 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.default = | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.default = parseOpenable; | ||
// From the nuclide-fuzzy-filename-provider module | ||
parseOpenable; // From the nuclide-fuzzy-filename-provider module | ||
// TODO: Remove that module when Dash and openables replace it | ||
@@ -21,14 +35,2 @@ /** | ||
* @format | ||
*/ | ||
function parseOpenable(query) { | ||
const [uri, line, column] = query.split(/:+/); | ||
const lineNumber = parseInt(line, 10); | ||
const columnNumber = parseInt(column, 10); | ||
return { | ||
uri, | ||
line: !Number.isNaN(lineNumber) ? lineNumber - 1 : undefined, | ||
column: !Number.isNaN(columnNumber) ? columnNumber - 1 : undefined | ||
}; | ||
} | ||
*/function parseOpenable(query) {const [uri, line, column] = query.split(/:+/);const lineNumber = parseInt(line, 10);const columnNumber = parseInt(column, 10);return { uri, line: !Number.isNaN(lineNumber) ? lineNumber - 1 : undefined, column: !Number.isNaN(columnNumber) ? columnNumber - 1 : undefined };} |
303
projects.js
@@ -1,165 +0,184 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports. | ||
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; | ||
exports.observeRemovedHostnames = observeRemovedHostnames; | ||
exports.observeAddedHostnames = observeAddedHostnames; | ||
var _atom = require('atom'); | ||
var _event; | ||
function _load_event() { | ||
return _event = require('nuclide-commons/event'); | ||
} | ||
var _nuclideUri; | ||
function _load_nuclideUri() { | ||
return _nuclideUri = _interopRequireDefault(require('nuclide-commons/nuclideUri')); | ||
} | ||
var _observable; | ||
function _load_observable() { | ||
return _observable = require('nuclide-commons/observable'); | ||
} | ||
var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
/** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ | ||
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()); | ||
} | ||
function getAtomProjectRelativePath(path) { | ||
const [projectPath, relativePath] = atom.project.relativizePath(path); | ||
if (!projectPath) { | ||
return null; | ||
} | ||
return relativePath; | ||
} | ||
function getAtomProjectRootPath(path) { | ||
const [projectPath] = atom.project.relativizePath(path); | ||
return projectPath; | ||
} | ||
/** | ||
* Like `atom.project.relativizePath`, except it returns the `Directory` rather than the path. | ||
* It also works for non-children, i.e. this can return `../../x`. | ||
* | ||
* This is intended to be used as a way to get a File object for any path | ||
* without worrying about remote vs. local paths. | ||
*/ | ||
function relativizePathWithDirectory(path) { | ||
for (const directory of atom.project.getDirectories()) { | ||
try { | ||
const relativePath = (_nuclideUri || _load_nuclideUri()).default.relative(directory.getPath(), path); | ||
return [directory, relativePath]; | ||
} catch (e) { | ||
// We have a remote-local mismatch or hostname mismatch. | ||
} | ||
} | ||
return [null, path]; | ||
} | ||
function getDirectoryForPath(path) { | ||
const [directory, relativePath] = relativizePathWithDirectory(path); | ||
if (directory == null) { | ||
return null; | ||
} | ||
return directory.getSubdirectory(relativePath); | ||
} | ||
function getFileForPath(path) { | ||
const [directory, relativePath] = relativizePathWithDirectory(path); | ||
if (directory == null) { | ||
return null; | ||
} | ||
return directory.getFile(relativePath); | ||
} | ||
function observeProjectPaths(callback) { | ||
getValidProjectPaths().forEach(callback); | ||
return onDidAddProjectPath(callback); | ||
} | ||
function onDidAddProjectPath(callback) { | ||
let projectPaths = getValidProjectPaths(); | ||
let changing = false; | ||
return atom.project.onDidChangePaths(() => { | ||
if (changing) { | ||
throw new Error('Cannot update projects in the middle of an update'); | ||
} | ||
changing = true; | ||
const newProjectPaths = getValidProjectPaths(); | ||
for (const newProjectPath of newProjectPaths) { | ||
if (!projectPaths.includes(newProjectPath)) { | ||
callback(newProjectPath); | ||
} | ||
} | ||
changing = false; | ||
projectPaths = newProjectPaths; | ||
}); | ||
} | ||
function onDidRemoveProjectPath(callback) { | ||
let projectPaths = getValidProjectPaths(); | ||
let changing = false; | ||
return atom.project.onDidChangePaths(() => { | ||
if (changing) { | ||
throw new Error('Cannot update projects in the middle of an update'); | ||
} | ||
changing = true; | ||
const newProjectPaths = getValidProjectPaths(); | ||
for (const projectPath of projectPaths) { | ||
if (!newProjectPaths.includes(projectPath)) { | ||
callback(projectPath); | ||
} | ||
} | ||
changing = false; | ||
projectPaths = newProjectPaths; | ||
}); | ||
} | ||
function observeHostnames() { | ||
return (atom.packages.initialPackagesActivated ? _rxjsBundlesRxMinJs.Observable.of(null) : (0, (_event || _load_event()).observableFromSubscribeFunction)(atom.packages.onDidActivateInitialPackages.bind(atom.packages))).switchMap(() => (0, (_event || _load_event()).observableFromSubscribeFunction)(atom.project.onDidChangePaths.bind(atom.project)).startWith(null).map(() => new Set(atom.project.getPaths().filter((_nuclideUri || _load_nuclideUri()).default.isRemote).map((_nuclideUri || _load_nuclideUri()).default.getHostname))).let((0, (_observable || _load_observable()).diffSets)())); | ||
} | ||
function observeRemovedHostnames() { | ||
return observeHostnames().flatMap(diff => _rxjsBundlesRxMinJs.Observable.from(diff.removed)); | ||
} | ||
function observeAddedHostnames() { | ||
return observeHostnames().flatMap(diff => _rxjsBundlesRxMinJs.Observable.from(diff.added)); | ||
} | ||
getAtomProjectRelativePath = getAtomProjectRelativePath;exports. | ||
getAtomProjectRootPath = getAtomProjectRootPath;exports. | ||
relativizePathWithDirectory = relativizePathWithDirectory;exports. | ||
getDirectoryForPath = getDirectoryForPath;exports. | ||
getFileForPath = getFileForPath;exports. | ||
observeProjectPaths = observeProjectPaths;exports. | ||
onDidAddProjectPath = onDidAddProjectPath;exports. | ||
onDidRemoveProjectPath = onDidRemoveProjectPath;exports. | ||
observeRemovedHostnames = observeRemovedHostnames;exports. | ||
observeAddedHostnames = observeAddedHostnames;var _atom = require('atom');var _event;function _load_event() {return _event = require('nuclide-commons/event');}var _nuclideUri;function _load_nuclideUri() {return _nuclideUri = _interopRequireDefault(require('nuclide-commons/nuclideUri'));}var _observable;function _load_observable() {return _observable = require('nuclide-commons/observable');}var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js');function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} /** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/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());}function getAtomProjectRelativePath(path) {const [projectPath, relativePath] = atom.project.relativizePath(path);if (!projectPath) {return null;}return relativePath;}function getAtomProjectRootPath(path) {const [projectPath] = atom.project.relativizePath(path);return projectPath;} /** | ||
* Like `atom.project.relativizePath`, except it returns the `Directory` rather than the path. | ||
* It also works for non-children, i.e. this can return `../../x`. | ||
* | ||
* This is intended to be used as a way to get a File object for any path | ||
* without worrying about remote vs. local paths. | ||
*/function relativizePathWithDirectory(path) {for (const directory of atom.project.getDirectories()) {try {const relativePath = (_nuclideUri || _load_nuclideUri()).default.relative(directory.getPath(), path);return [directory, relativePath];} catch (e) {// We have a remote-local mismatch or hostname mismatch. | ||
}}return [null, path];}function getDirectoryForPath(path) {const [directory, relativePath] = relativizePathWithDirectory(path);if (directory == null) {return null;}return directory.getSubdirectory(relativePath);}function getFileForPath(path) {const [directory, relativePath] = relativizePathWithDirectory(path);if (directory == null) {return null;}return directory.getFile(relativePath);}function observeProjectPaths(callback) {getValidProjectPaths().forEach(callback);return onDidAddProjectPath(callback);}function onDidAddProjectPath(callback) {let projectPaths = getValidProjectPaths();let changing = false;return atom.project.onDidChangePaths(() => {if (changing) {throw new Error('Cannot update projects in the middle of an update');}changing = true;const newProjectPaths = getValidProjectPaths();for (const newProjectPath of newProjectPaths) {if (!projectPaths.includes(newProjectPath)) {callback(newProjectPath);}}changing = false;projectPaths = newProjectPaths;});}function onDidRemoveProjectPath(callback) {let projectPaths = getValidProjectPaths();let changing = false;return atom.project.onDidChangePaths(() => {if (changing) {throw new Error('Cannot update projects in the middle of an update');}changing = true;const newProjectPaths = getValidProjectPaths();for (const projectPath of projectPaths) {if (!newProjectPaths.includes(projectPath)) {callback(projectPath);}}changing = false;projectPaths = newProjectPaths;});}function observeHostnames() {return (atom.packages.initialPackagesActivated ? _rxjsBundlesRxMinJs.Observable.of(null) : (0, (_event || _load_event()).observableFromSubscribeFunction)(atom.packages.onDidActivateInitialPackages.bind(atom.packages))).switchMap(() => (0, (_event || _load_event()).observableFromSubscribeFunction)(atom.project.onDidChangePaths.bind(atom.project)).startWith(null).map(() => new Set(atom.project.getPaths().filter((_nuclideUri || _load_nuclideUri()).default.isRemote).map((_nuclideUri || _load_nuclideUri()).default.getHostname))).let((0, (_observable || _load_observable()).diffSets)()));}function observeRemovedHostnames() {return observeHostnames().flatMap(diff => _rxjsBundlesRxMinJs.Observable.from(diff.removed));}function observeAddedHostnames() {return observeHostnames().flatMap(diff => _rxjsBundlesRxMinJs.Observable.from(diff.added));} |
@@ -1,17 +0,25 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });var _UniversalDisposable; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
var _UniversalDisposable; | ||
function _load_UniversalDisposable() { | ||
return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable')); | ||
} | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function _load_UniversalDisposable() {return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable'));}function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} | ||
class ProviderRegistry { | ||
constructor() { | ||
@@ -22,3 +30,5 @@ this._providers = []; | ||
addProvider(provider) { | ||
const index = this._providers.findIndex(p => provider.priority > p.priority); | ||
const index = this._providers.findIndex( | ||
p => provider.priority > p.priority); | ||
if (index === -1) { | ||
@@ -59,22 +69,23 @@ this._providers.push(provider); | ||
/** | ||
* Iterates over all providers matching the grammar, in priority order. | ||
*/ | ||
* Iterates over all providers matching the grammar, in priority order. | ||
*/ | ||
*findAllProviders(grammar) { | ||
for (const provider of this._providers) { | ||
if (provider.grammarScopes == null || provider.grammarScopes.indexOf(grammar) !== -1) { | ||
if ( | ||
provider.grammarScopes == null || | ||
provider.grammarScopes.indexOf(grammar) !== -1) | ||
{ | ||
yield provider; | ||
} | ||
} | ||
} | ||
} | ||
exports.default = ProviderRegistry; /** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ | ||
}}exports.default = ProviderRegistry; /** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ |
157
range.js
@@ -1,88 +0,95 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports. | ||
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'); | ||
} | ||
var _textEditor; | ||
function _load_textEditor() { | ||
return _textEditor = require('./text-editor'); | ||
} | ||
/** | ||
* Finds the word at the position. You can either provide a word regex yourself, | ||
* or have Atom use the word regex in force at the scopes at that position, | ||
* in which case it uses the optional includeNonWordCharacters, default true. | ||
* (I know that's a weird default but it follows Atom's convention...) | ||
*/ | ||
function wordAtPosition(editor, position, wordRegex) { | ||
let wordRegex_; | ||
if (wordRegex instanceof RegExp) { | ||
wordRegex_ = wordRegex; | ||
} else { | ||
// What is the word regex associated with the position? We'd like to use | ||
wordAtPosition = wordAtPosition;exports. | ||
trimRange = trimRange;var _atom = require('atom');var _range;function _load_range() {return _range = require('nuclide-commons/range');}var _textEditor;function _load_textEditor() {return _textEditor = require('./text-editor');} /** | ||
* Finds the word at the position. You can either provide a word regex yourself, | ||
* or have Atom use the word regex in force at the scopes at that position, | ||
* in which case it uses the optional includeNonWordCharacters, default true. | ||
* (I know that's a weird default but it follows Atom's convention...) | ||
*/function wordAtPosition(editor, position, wordRegex) {let wordRegex_;if (wordRegex instanceof RegExp) {wordRegex_ = wordRegex;} else {// What is the word regex associated with the position? We'd like to use | ||
// atom$Cursor.wordRegExp, except that function gets the regex associated | ||
// with the editor's current cursor while we want the regex associated with | ||
// the specific position. So we re-implement it ourselves... | ||
const nonWordChars = (0, (_textEditor || _load_textEditor()).getNonWordCharacters)(editor, position); | ||
const escaped = nonWordChars.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'); | ||
// We copied this escaping regex from atom$Cursor.wordRegexp, rather than | ||
const nonWordChars = (0, (_textEditor || _load_textEditor()).getNonWordCharacters)(editor, position);const escaped = nonWordChars.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'); // We copied this escaping regex from atom$Cursor.wordRegexp, rather than | ||
// using the library function 'escapeStringRegExp'. That's because the | ||
// library function doesn't escape the hyphen character and so is | ||
// unsuitable for use inside a range. | ||
let r = `^[\t ]*$|[^\\s${escaped}]+`; | ||
if (wordRegex == null || wordRegex.includeNonWordCharacters) { | ||
r += `|[${escaped}]+`; | ||
} | ||
wordRegex_ = new RegExp(r, 'g'); | ||
} | ||
return (0, (_range || _load_range()).wordAtPositionFromBuffer)(editor.getBuffer(), position, wordRegex_); | ||
} | ||
/** | ||
* Gets the trimmed range from a given range, i.e. moves the start and end points | ||
* to the first and last non-whitespace characters (or specified regex) | ||
* within the range respectively. | ||
* | ||
* @param editor the editor containing the range | ||
* @param rangeToTrim the range to trim | ||
* @param stopRegex stop trimming when the first match is found for this regex, | ||
* defaults to first non-whitespace character | ||
* @return atom$Range the trimmed range | ||
*/ | ||
/** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ | ||
function trimRange(editor, rangeToTrim, stopRegex = /\S/) { | ||
const buffer = editor.getBuffer(); | ||
let { start, end } = rangeToTrim; | ||
buffer.scanInRange(stopRegex, rangeToTrim, ({ range, stop }) => { | ||
start = range.start; | ||
stop(); | ||
}); | ||
buffer.backwardsScanInRange(stopRegex, rangeToTrim, ({ range, stop }) => { | ||
end = range.end; | ||
stop(); | ||
}); | ||
return new _atom.Range(start, end); | ||
} | ||
let r = `^[\t ]*$|[^\\s${escaped}]+`;if (wordRegex == null || wordRegex.includeNonWordCharacters) {r += `|[${escaped}]+`;}wordRegex_ = new RegExp(r, 'g');}return (0, (_range || _load_range()).wordAtPositionFromBuffer)(editor.getBuffer(), position, wordRegex_);} /** | ||
* Gets the trimmed range from a given range, i.e. moves the start and end points | ||
* to the first and last non-whitespace characters (or specified regex) | ||
* within the range respectively. | ||
* | ||
* @param editor the editor containing the range | ||
* @param rangeToTrim the range to trim | ||
* @param stopRegex stop trimming when the first match is found for this regex, | ||
* defaults to first non-whitespace character | ||
* @return atom$Range the trimmed range | ||
*/ /** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/function trimRange(editor, rangeToTrim, stopRegex = /\S/) {const buffer = editor.getBuffer();let { start, end } = rangeToTrim;buffer.scanInRange(stopRegex, rangeToTrim, ({ range, stop }) => {start = range.start;stop();});buffer.backwardsScanInRange(stopRegex, rangeToTrim, ({ range, stop }) => {end = range.end;stop();});return new _atom.Range(start, end);} |
@@ -1,33 +0,56 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.default = | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.default = createLoggerMiddleware; | ||
var _reduxLogger; | ||
function _load_reduxLogger() { | ||
return _reduxLogger = require('redux-logger'); | ||
} | ||
var _featureConfig; | ||
function _load_featureConfig() { | ||
return _featureConfig = _interopRequireDefault(require('./feature-config')); | ||
} | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
/* | ||
To turn on debug console logging for the feature you are debugging, add to your config.cson: | ||
"*": | ||
"nuclide": | ||
"redux-debug-loggers": [ | ||
"<YOUR_APP_NAME>" | ||
] | ||
*/ | ||
// More options can be found here if you wish to enable them: | ||
createLoggerMiddleware;var _reduxLogger;function _load_reduxLogger() {return _reduxLogger = require('redux-logger');}var _featureConfig;function _load_featureConfig() {return _featureConfig = _interopRequireDefault(require('./feature-config'));}function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} /* | ||
To turn on debug console logging for the feature you are debugging, add to your config.cson: | ||
"*": | ||
"nuclide": | ||
"redux-debug-loggers": [ | ||
"<YOUR_APP_NAME>" | ||
] | ||
*/ // More options can be found here if you wish to enable them: | ||
// https://github.com/evgenyrodionov/redux-logger#options | ||
@@ -44,14 +67,2 @@ /** | ||
* @format | ||
*/ | ||
const enabledLoggers = (_featureConfig || _load_featureConfig()).default.getWithDefaults('redux-debug-loggers', []); | ||
const noopMiddleware = store => next => action => next(action); | ||
function createLoggerMiddleware(appName, loggerConfig) { | ||
if (!enabledLoggers.includes(appName)) { | ||
return noopMiddleware; | ||
} | ||
return (0, (_reduxLogger || _load_reduxLogger()).createLogger)(loggerConfig); | ||
} | ||
*/const enabledLoggers = (_featureConfig || _load_featureConfig()).default.getWithDefaults('redux-debug-loggers', []);const noopMiddleware = store => next => action => next(action);function createLoggerMiddleware(appName, loggerConfig) {if (!enabledLoggers.includes(appName)) {return noopMiddleware;}return (0, (_reduxLogger || _load_reduxLogger()).createLogger)(loggerConfig);} |
@@ -1,16 +0,22 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports. | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.jasmineAttachWorkspace = jasmineAttachWorkspace; | ||
// Attach the Atom workspace to the DOM, and give it a reasonable size. | ||
jasmineAttachWorkspace = jasmineAttachWorkspace; // Attach the Atom workspace to the DOM, and give it a reasonable size. | ||
// This is important for tests that touch the text editor in 1.19+, as they'll have a height of 0 | ||
// unless properly attached with a valid viewport. | ||
function jasmineAttachWorkspace() { | ||
jasmine.attachToDOM(atom.views.getView(atom.workspace)); | ||
// Set the testing window dimensions (smallish, yet realistic). | ||
function jasmineAttachWorkspace() {jasmine.attachToDOM(atom.views.getView(atom.workspace)); // Set the testing window dimensions (smallish, yet realistic). | ||
const styleCSS = ` | ||
@@ -20,8 +26,4 @@ height: 600px; | ||
`; | ||
const content = document.querySelector('#jasmine-content'); | ||
if (!(content != null)) { | ||
throw new Error('Invariant violation: "content != null"'); | ||
} | ||
const content = document.querySelector('#jasmine-content');if (!( | ||
content != null)) {throw new Error('Invariant violation: "content != null"');} | ||
content.setAttribute('style', styleCSS); | ||
@@ -28,0 +30,0 @@ |
@@ -1,13 +0,32 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports. | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.toUnifiedDiff = toUnifiedDiff; | ||
var _atom = require('atom'); | ||
function toUnifiedDiff(filename, buffer, edits, contextRows = 1) { | ||
toUnifiedDiff = toUnifiedDiff;var _atom = require('atom');function toUnifiedDiff( | ||
filename, | ||
buffer, | ||
edits, | ||
contextRows = 1) | ||
{ | ||
const hunks = getHunks(buffer, edits, contextRows); | ||
return [`--- ${filename}`, `+++ ${filename}`].concat(mapHunkToString(buffer, hunks, contextRows)).join('\n'); | ||
return [`--- ${filename}`, `+++ ${filename}`]. | ||
concat(mapHunkToString(buffer, hunks, contextRows)). | ||
join('\n'); | ||
} /** | ||
@@ -23,9 +42,7 @@ * Copyright (c) 2017-present, Facebook, Inc. | ||
* @format | ||
*/ | ||
function getHunks(buffer, edits, contextRows) { | ||
return edits.sort((e1, e2) => e1.oldRange.compare(e2.oldRange)).reduce((mergedEdits, nextEdit) => { | ||
const edit = mergedEdits[mergedEdits.length - 1]; | ||
if (edit && nextEdit.oldRange.start.row <= edit.oldRange.end.row + contextRows) { | ||
*/function getHunks(buffer, edits, contextRows) {return edits.sort((e1, e2) => e1.oldRange.compare(e2.oldRange)).reduce((mergedEdits, nextEdit) => {const edit = mergedEdits[mergedEdits.length - 1]; | ||
if ( | ||
edit && | ||
nextEdit.oldRange.start.row <= edit.oldRange.end.row + contextRows) | ||
{ | ||
mergedEdits[mergedEdits.length - 1] = mergeEdit(buffer, edit, nextEdit); | ||
@@ -36,6 +53,10 @@ } else { | ||
return mergedEdits; | ||
}, []).map(edit => { | ||
}, []). | ||
map(edit => { | ||
const oldRange = edit.oldRange; | ||
const rows = oldRange.getRows(); | ||
const newText = buffer.lineForRow(rows[0]).substring(0, oldRange.start.column) + edit.newText + buffer.lineForRow(rows[rows.length - 1]).substring(oldRange.end.column); | ||
const newText = | ||
buffer.lineForRow(rows[0]).substring(0, oldRange.start.column) + | ||
edit.newText + | ||
buffer.lineForRow(rows[rows.length - 1]).substring(oldRange.end.column); | ||
const newLines = newText.split(/\r\n|\r|\n/); | ||
@@ -46,9 +67,13 @@ return { rows, newLines }; | ||
function mergeEdit(buffer, e1, e2) { | ||
if (!e1.oldRange.end.isLessThanOrEqual(e2.oldRange.start)) { | ||
throw new Error('Invariant violation: "e1.oldRange.end.isLessThanOrEqual(e2.oldRange.start)"'); | ||
} | ||
function mergeEdit( | ||
buffer, | ||
e1, | ||
e2) | ||
{if (! | ||
e1.oldRange.end.isLessThanOrEqual(e2.oldRange.start)) {throw new Error('Invariant violation: "e1.oldRange.end.isLessThanOrEqual(e2.oldRange.start)"');} | ||
const mergedEdit = {}; | ||
mergedEdit.newText = e1.newText + buffer.getTextInRange(new _atom.Range(e1.oldRange.end, e2.oldRange.start)) + e2.newText; | ||
mergedEdit.newText = | ||
e1.newText + | ||
buffer.getTextInRange(new _atom.Range(e1.oldRange.end, e2.oldRange.start)) + | ||
e2.newText; | ||
mergedEdit.oldRange = e1.oldRange.union(e2.oldRange); | ||
@@ -58,3 +83,7 @@ return mergedEdit; | ||
function mapHunkToString(buffer, hunks, contextRows) { | ||
function mapHunkToString( | ||
buffer, | ||
hunks, | ||
contextRows) | ||
{ | ||
// This requires storing some state across the map() to compute the row | ||
@@ -83,3 +112,5 @@ // numbers correctly. | ||
const parts = []; | ||
parts.push(`@@ -${oldBeginRow},${oldRowLength} +${newBeginRow},${newRowLength} @@`); | ||
parts.push( | ||
`@@ -${oldBeginRow},${oldRowLength} +${newBeginRow},${newRowLength} @@`); | ||
beforeRows.forEach(row => { | ||
@@ -86,0 +117,0 @@ parts.push(' ' + buffer.lineForRow(row)); |
194
text-edit.js
@@ -1,29 +0,48 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.applyTextEditsForMultipleFiles = undefined;var _asyncToGenerator = _interopRequireDefault(require('async-to-generator')); | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.applyTextEditsForMultipleFiles = undefined; | ||
var _asyncToGenerator = _interopRequireDefault(require('async-to-generator')); | ||
/** | ||
* Attempts to apply the given patches for multiple files. Accepts a Map as input | ||
* with file paths as keys and a corresponding array of TextEdits as values. | ||
* | ||
* It is an error to send overlapping text-edits. All text-edits describe changes | ||
* made to the initial document version. The order of the edits does not matter | ||
* as they will be sorted before they are applied. | ||
* | ||
* All changes will be applied to the buffers but not saved. If a file is not | ||
* currently open, it will be opened. | ||
* | ||
* If a change is undone (Cmd+Z), only the changes of the current | ||
* file will be undone. All of the changes for that file will be undone at once. | ||
* | ||
* Returns true if the application was successful, otherwise false. If any of | ||
* the changes fail, for ANY file, then none of the changes are applied. | ||
*/ | ||
let applyTextEditsForMultipleFiles = exports.applyTextEditsForMultipleFiles = (() => { | ||
var _ref = (0, _asyncToGenerator.default)(function* (changes) { | ||
* Attempts to apply the given patches for multiple files. Accepts a Map as input | ||
* with file paths as keys and a corresponding array of TextEdits as values. | ||
* | ||
* It is an error to send overlapping text-edits. All text-edits describe changes | ||
* made to the initial document version. The order of the edits does not matter | ||
* as they will be sorted before they are applied. | ||
* | ||
* All changes will be applied to the buffers but not saved. If a file is not | ||
* currently open, it will be opened. | ||
* | ||
* If a change is undone (Cmd+Z), only the changes of the current | ||
* file will be undone. All of the changes for that file will be undone at once. | ||
* | ||
* Returns true if the application was successful, otherwise false. If any of | ||
* the changes fail, for ANY file, then none of the changes are applied. | ||
*/let applyTextEditsForMultipleFiles = exports.applyTextEditsForMultipleFiles = (() => {var _ref = (0, _asyncToGenerator.default)( | ||
function* ( | ||
changes) | ||
{ | ||
const paths = Array.from(changes.keys()); | ||
@@ -34,16 +53,7 @@ | ||
// However, currently this is only used to applyEdits to open files. | ||
const editors = yield Promise.all(paths.map((() => { | ||
var _ref2 = (0, _asyncToGenerator.default)(function* (path) { | ||
return (0, (_goToLocation || _load_goToLocation()).goToLocation)(path); | ||
}); | ||
const editors = yield Promise.all( | ||
paths.map((() => {var _ref2 = (0, _asyncToGenerator.default)(function* (path) {return (0, (_goToLocation || _load_goToLocation()).goToLocation)(path);});return function (_x2) {return _ref2.apply(this, arguments);};})())); | ||
return function (_x2) { | ||
return _ref2.apply(this, arguments); | ||
}; | ||
})())); | ||
const checkpoints = editors.map(function (editor) { | ||
if (!(editor != null)) { | ||
throw new Error('Invariant violation: "editor != null"'); | ||
} | ||
const checkpoints = editors.map(function (editor) {if (!( | ||
editor != null)) {throw new Error('Invariant violation: "editor != null"');} | ||
const buffer = editor.getBuffer(); | ||
@@ -63,76 +73,43 @@ return [buffer, buffer.createCheckpoint()]; | ||
return allOkay; | ||
}); | ||
});return function applyTextEditsForMultipleFiles(_x) {return _ref.apply(this, arguments);};})(); | ||
return function applyTextEditsForMultipleFiles(_x) { | ||
return _ref.apply(this, arguments); | ||
}; | ||
})(); | ||
/** | ||
* Attempts to apply the given patches to the given file. | ||
* | ||
* It is an error to send overlapping edits. The order of the edits does not | ||
* matter (they will be sorted before they are applied). | ||
* | ||
* The file must be currently open in Atom, and the changes will be applied to the buffer but not | ||
* saved. | ||
* | ||
* Returns true if the application was successful, otherwise false (e.g. if the oldText did not | ||
* match). | ||
*/ | ||
/** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ | ||
exports.applyTextEdits = applyTextEdits; | ||
exports.applyTextEditsToBuffer = applyTextEditsToBuffer; | ||
var _log4js; | ||
function _load_log4js() { | ||
return _log4js = require('log4js'); | ||
} | ||
var _textEditor; | ||
function _load_textEditor() { | ||
return _textEditor = require('./text-editor'); | ||
} | ||
var _goToLocation; | ||
function _load_goToLocation() { | ||
return _goToLocation = require('./go-to-location'); | ||
} | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function applyTextEdits(path, ...edits) { | ||
const sortedEdits = sortEdits(edits); | ||
const editor = (0, (_textEditor || _load_textEditor()).existingEditorForUri)(path); | ||
if (!(editor != null)) { | ||
throw new Error('Invariant violation: "editor != null"'); | ||
} | ||
return applySortedTextEditsToBuffer(editor.getBuffer(), sortedEdits); | ||
} | ||
function applyTextEditsToBuffer(buffer, edits) { | ||
* Attempts to apply the given patches to the given file. | ||
* | ||
* It is an error to send overlapping edits. The order of the edits does not | ||
* matter (they will be sorted before they are applied). | ||
* | ||
* The file must be currently open in Atom, and the changes will be applied to the buffer but not | ||
* saved. | ||
* | ||
* Returns true if the application was successful, otherwise false (e.g. if the oldText did not | ||
* match). | ||
*/ /** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/exports.applyTextEdits = applyTextEdits;exports. | ||
applyTextEditsToBuffer = applyTextEditsToBuffer;var _log4js;function _load_log4js() {return _log4js = require('log4js');}var _textEditor;function _load_textEditor() {return _textEditor = require('./text-editor');}var _goToLocation;function _load_goToLocation() {return _goToLocation = require('./go-to-location');}function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}function applyTextEdits(path, ...edits) {const sortedEdits = sortEdits(edits);const editor = (0, (_textEditor || _load_textEditor()).existingEditorForUri)(path);if (!(editor != null)) {throw new Error('Invariant violation: "editor != null"');}return applySortedTextEditsToBuffer(editor.getBuffer(), sortedEdits);}function applyTextEditsToBuffer( | ||
buffer, | ||
edits) | ||
{ | ||
return applySortedTextEditsToBuffer(buffer, sortEdits(edits)); | ||
} | ||
function applySortedTextEditsToBuffer(buffer, edits) { | ||
function applySortedTextEditsToBuffer( | ||
buffer, | ||
edits) | ||
{ | ||
// For every edit, the start of its range will be after the end of the | ||
// previous edit's range. | ||
if (editsOverlap(edits)) { | ||
(0, (_log4js || _load_log4js()).getLogger)('text-edit').warn('applyTextEdits was called with overlapping edits.'); | ||
(0, (_log4js || _load_log4js()).getLogger)('text-edit').warn( | ||
'applyTextEdits was called with overlapping edits.'); | ||
return false; | ||
@@ -189,3 +166,7 @@ } | ||
for (let i = 0; i < sortedEdits.length - 1; i++) { | ||
if (sortedEdits[i].oldRange.end.isGreaterThan(sortedEdits[i + 1].oldRange.start)) { | ||
if ( | ||
sortedEdits[i].oldRange.end.isGreaterThan( | ||
sortedEdits[i + 1].oldRange.start)) | ||
{ | ||
return true; | ||
@@ -199,3 +180,6 @@ } | ||
// stable sort (preserve order of edits starting in the same location) | ||
return edits.map((edit, i) => [edit, i]).sort(([e1, i1], [e2, i2]) => e1.oldRange.compare(e2.oldRange) || i1 - i2).map(([edit]) => edit); | ||
return edits. | ||
map((edit, i) => [edit, i]). | ||
sort(([e1, i1], [e2, i2]) => e1.oldRange.compare(e2.oldRange) || i1 - i2). | ||
map(([edit]) => edit); | ||
} |
@@ -1,247 +0,296 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports. | ||
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.enforceReadOnlyEditor = enforceReadOnlyEditor; | ||
exports.enforceSoftWrap = enforceSoftWrap; | ||
exports.observeTextEditors = observeTextEditors; | ||
exports.isValidTextEditor = isValidTextEditor; | ||
exports.centerScrollToBufferLine = centerScrollToBufferLine; | ||
exports.getNonWordCharacters = getNonWordCharacters; | ||
var _UniversalDisposable; | ||
function _load_UniversalDisposable() { | ||
return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable')); | ||
} | ||
var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js'); | ||
var _semver; | ||
function _load_semver() { | ||
return _semver = _interopRequireDefault(require('semver')); | ||
} | ||
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 }; } | ||
/** | ||
* Returns a text editor that has the given path open, or null if none exists. If there are multiple | ||
* text editors for this path, one is chosen arbitrarily. | ||
*/ | ||
function existingEditorForUri(path) { | ||
// This isn't ideal but realistically iterating through even a few hundred editors shouldn't be a | ||
// real problem. And if you have more than a few hundred you probably have bigger problems. | ||
for (const editor of atom.workspace.getTextEditors()) { | ||
if (editor.getPath() === path) { | ||
return editor; | ||
} | ||
} | ||
return null; | ||
} | ||
/** | ||
* Returns a text editor that has the given buffer open, or null if none exists. If there are | ||
* multiple text editors for this buffer, one is chosen arbitrarily. | ||
*/ | ||
/** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ | ||
function existingEditorForBuffer(buffer) { | ||
// This isn't ideal but realistically iterating through even a few hundred editors shouldn't be a | ||
// real problem. And if you have more than a few hundred you probably have bigger problems. | ||
for (const editor of atom.workspace.getTextEditors()) { | ||
if (editor.getBuffer() === buffer) { | ||
return editor; | ||
} | ||
} | ||
return null; | ||
} | ||
function getViewOfEditor(editor) { | ||
return atom.views.getView(editor); | ||
} | ||
function getScrollTop(editor) { | ||
return getViewOfEditor(editor).getScrollTop(); | ||
} | ||
function setScrollTop(editor, scrollTop) { | ||
getViewOfEditor(editor).setScrollTop(scrollTop); | ||
} | ||
/** | ||
* Does a best effort to set an editor pane to a given cursor position & scroll. | ||
* Does not ensure that the current cursor position is visible. | ||
* | ||
* Can be used with editor.getCursorBufferPosition() & getScrollTop() to restore | ||
* an editors cursor and scroll. | ||
*/ | ||
function setPositionAndScroll(editor, position, scrollTop) { | ||
editor.setCursorBufferPosition(position, { autoscroll: false }); | ||
setScrollTop(editor, scrollTop); | ||
} | ||
function getCursorPositions(editor) { | ||
return _rxjsBundlesRxMinJs.Observable.defer(() => { | ||
// This will behave strangely in the face of multiple cursors. Consider supporting multiple | ||
// cursors in the future. | ||
const cursor = editor.getCursors()[0]; | ||
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)); | ||
}); | ||
} | ||
function observeEditorDestroy(editor) { | ||
return (0, (_event || _load_event()).observableFromSubscribeFunction)(editor.onDidDestroy.bind(editor)).map(event => editor).take(1); | ||
} | ||
// As of the introduction of atom.workspace.buildTextEditor(), it is no longer possible to | ||
// subclass TextEditor to create a ReadOnlyTextEditor. Instead, the way to achieve this effect | ||
// is to create an ordinary TextEditor and then override any methods that would allow it to | ||
// change its contents. | ||
// TODO: https://github.com/atom/atom/issues/9237. | ||
function enforceReadOnlyEditor(textEditor, readOnlyExceptions = ['append', 'setText']) { | ||
// Cancel insert events to prevent typing in the text editor and disallow editing (read-only). | ||
const willInsertTextDisposable = textEditor.onWillInsertText(event => { | ||
event.cancel(); | ||
}); | ||
existingEditorForUri = existingEditorForUri;exports. | ||
return new (_UniversalDisposable || _load_UniversalDisposable()).default(willInsertTextDisposable, | ||
// `setText` & `append` are the only exceptions that's used to set the read-only text. | ||
enforceReadOnlyBuffer(textEditor.getBuffer(), readOnlyExceptions)); | ||
} | ||
function enforceReadOnlyBuffer(textBuffer, readOnlyExceptions = []) { | ||
const noop = () => {}; | ||
// All user edits use `transact` - so, mocking this will effectively make the editor read-only. | ||
const originalApplyChange = textBuffer.applyChange; | ||
const originalReadOnlyExceptionFunctions = {}; | ||
textBuffer.applyChange = noop; | ||
readOnlyExceptions.forEach(passReadOnlyException); | ||
function passReadOnlyException(functionName) { | ||
const buffer = textBuffer; | ||
const originalFunction = buffer[functionName]; | ||
originalReadOnlyExceptionFunctions[functionName] = originalFunction; | ||
buffer[functionName] = function () { | ||
textBuffer.applyChange = originalApplyChange; | ||
const result = originalFunction.apply(textBuffer, arguments); | ||
textBuffer.applyChange = noop; | ||
return result; | ||
}; | ||
} | ||
return new (_UniversalDisposable || _load_UniversalDisposable()).default(() => { | ||
textBuffer.applyChange = originalApplyChange; | ||
const buffer = textBuffer; | ||
readOnlyExceptions.forEach(functionName => buffer[functionName] = originalReadOnlyExceptionFunctions[functionName]); | ||
}); | ||
} | ||
// Turn off soft wrap setting for these editors so diffs properly align. | ||
// Some text editor register sometimes override the set soft wrapping | ||
// after mounting an editor to the workspace - here, that's watched and reset to `false`. | ||
function enforceSoftWrap(editor, enforcedSoftWrap) { | ||
editor.setSoftWrapped(enforcedSoftWrap); | ||
return editor.onDidChangeSoftWrapped(softWrapped => { | ||
if (softWrapped !== enforcedSoftWrap) { | ||
// Reset the overridden softWrap to `false` once the operation completes. | ||
process.nextTick(() => { | ||
if (!editor.isDestroyed()) { | ||
editor.setSoftWrapped(enforcedSoftWrap); | ||
} | ||
}); | ||
} | ||
}); | ||
} | ||
/** | ||
* Small wrapper around `atom.workspace.observeTextEditors` that filters out | ||
* uninitialized remote editors. Most callers should use this one instead. | ||
*/ | ||
function observeTextEditors(callback) { | ||
// The one place where atom.workspace.observeTextEditors needs to be used. | ||
// eslint-disable-next-line rulesdir/atom-apis | ||
return atom.workspace.observeTextEditors(editor => { | ||
if (isValidTextEditor(editor)) { | ||
callback(editor); | ||
} | ||
}); | ||
} | ||
/** | ||
* Checks if an object (typically an Atom pane) is a TextEditor with a non-broken path. | ||
*/ | ||
function isValidTextEditor(item) { | ||
// eslint-disable-next-line rulesdir/atom-apis | ||
if (atom.workspace.isTextEditor(item)) { | ||
return !(_nuclideUri || _load_nuclideUri()).default.isBrokenDeserializedUri(item.getPath()); | ||
} | ||
return false; | ||
} | ||
function centerScrollToBufferLine(textEditorElement, bufferLineNumber) { | ||
const textEditor = textEditorElement.getModel(); | ||
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; | ||
textEditorElement.setScrollTop(Math.max(scrollTop, 1)); | ||
textEditorElement.focus(); | ||
textEditor.setCursorBufferPosition([bufferLineNumber, 0], { | ||
autoscroll: false | ||
}); | ||
} | ||
function getNonWordCharacters(editor, position) { | ||
if ((_semver || _load_semver()).default.gte(atom.getVersion(), '1.24.0-beta0')) { | ||
return editor.getNonWordCharacters(position); | ||
} else { | ||
// This used to take a scope descriptor. | ||
const scope = position == null ? null : editor.scopeDescriptorForBufferPosition(position); | ||
return editor.getNonWordCharacters(scope); | ||
} | ||
} | ||
existingEditorForBuffer = existingEditorForBuffer;exports. | ||
getViewOfEditor = getViewOfEditor;exports. | ||
getScrollTop = getScrollTop;exports. | ||
setScrollTop = setScrollTop;exports. | ||
setPositionAndScroll = setPositionAndScroll;exports. | ||
getCursorPositions = getCursorPositions;exports. | ||
observeEditorDestroy = observeEditorDestroy;exports. | ||
enforceReadOnlyEditor = enforceReadOnlyEditor;exports. | ||
enforceSoftWrap = enforceSoftWrap;exports. | ||
observeTextEditors = observeTextEditors;exports. | ||
isValidTextEditor = isValidTextEditor;exports. | ||
centerScrollToBufferLine = centerScrollToBufferLine;exports. | ||
getNonWordCharacters = getNonWordCharacters;var _UniversalDisposable;function _load_UniversalDisposable() {return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable'));}var _rxjsBundlesRxMinJs = require('rxjs/bundles/Rx.min.js');var _semver;function _load_semver() {return _semver = _interopRequireDefault(require('semver'));}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 };} /** | ||
* Returns a text editor that has the given path open, or null if none exists. If there are multiple | ||
* text editors for this path, one is chosen arbitrarily. | ||
*/function existingEditorForUri(path) {// This isn't ideal but realistically iterating through even a few hundred editors shouldn't be a | ||
// real problem. And if you have more than a few hundred you probably have bigger problems. | ||
for (const editor of atom.workspace.getTextEditors()) {if (editor.getPath() === path) {return editor;}}return null;} /** | ||
* Returns a text editor that has the given buffer open, or null if none exists. If there are | ||
* multiple text editors for this buffer, one is chosen arbitrarily. | ||
*/ /** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/function existingEditorForBuffer(buffer) {// This isn't ideal but realistically iterating through even a few hundred editors shouldn't be a | ||
// real problem. And if you have more than a few hundred you probably have bigger problems. | ||
for (const editor of atom.workspace.getTextEditors()) {if (editor.getBuffer() === buffer) {return editor;}}return null;}function getViewOfEditor(editor) {return atom.views.getView(editor);}function getScrollTop(editor) {return getViewOfEditor(editor).getScrollTop();}function setScrollTop(editor, scrollTop) {getViewOfEditor(editor).setScrollTop(scrollTop);} /** | ||
* Does a best effort to set an editor pane to a given cursor position & scroll. | ||
* Does not ensure that the current cursor position is visible. | ||
* | ||
* Can be used with editor.getCursorBufferPosition() & getScrollTop() to restore | ||
* an editors cursor and scroll. | ||
*/function setPositionAndScroll(editor, position, scrollTop) {editor.setCursorBufferPosition(position, { autoscroll: false });setScrollTop(editor, scrollTop);}function getCursorPositions(editor) {return _rxjsBundlesRxMinJs.Observable.defer(() => {// This will behave strangely in the face of multiple cursors. Consider supporting multiple | ||
// cursors in the future. | ||
const cursor = editor.getCursors()[0];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));});}function observeEditorDestroy(editor) {return (0, (_event || _load_event()).observableFromSubscribeFunction)(editor.onDidDestroy.bind(editor)).map(event => editor).take(1);} // As of the introduction of atom.workspace.buildTextEditor(), it is no longer possible to | ||
// subclass TextEditor to create a ReadOnlyTextEditor. Instead, the way to achieve this effect | ||
// is to create an ordinary TextEditor and then override any methods that would allow it to | ||
// change its contents. | ||
// TODO: https://github.com/atom/atom/issues/9237. | ||
function enforceReadOnlyEditor(textEditor, readOnlyExceptions = ['append', 'setText']) {// Cancel insert events to prevent typing in the text editor and disallow editing (read-only). | ||
const willInsertTextDisposable = textEditor.onWillInsertText(event => {event.cancel();});return new (_UniversalDisposable || _load_UniversalDisposable()).default(willInsertTextDisposable, // `setText` & `append` are the only exceptions that's used to set the read-only text. | ||
enforceReadOnlyBuffer(textEditor.getBuffer(), readOnlyExceptions));}function enforceReadOnlyBuffer(textBuffer, readOnlyExceptions = []) {const noop = () => {}; // All user edits use `transact` - so, mocking this will effectively make the editor read-only. | ||
const originalApplyChange = textBuffer.applyChange;const originalReadOnlyExceptionFunctions = {};textBuffer.applyChange = noop;readOnlyExceptions.forEach(passReadOnlyException);function passReadOnlyException(functionName) {const buffer = textBuffer;const originalFunction = buffer[functionName];originalReadOnlyExceptionFunctions[functionName] = originalFunction;buffer[functionName] = function () {textBuffer.applyChange = originalApplyChange;const result = originalFunction.apply(textBuffer, arguments);textBuffer.applyChange = noop;return result;};}return new (_UniversalDisposable || _load_UniversalDisposable()).default(() => {textBuffer.applyChange = originalApplyChange;const buffer = textBuffer;readOnlyExceptions.forEach(functionName => buffer[functionName] = originalReadOnlyExceptionFunctions[functionName]);});} // Turn off soft wrap setting for these editors so diffs properly align. | ||
// Some text editor register sometimes override the set soft wrapping | ||
// after mounting an editor to the workspace - here, that's watched and reset to `false`. | ||
function enforceSoftWrap(editor, enforcedSoftWrap) {editor.setSoftWrapped(enforcedSoftWrap);return editor.onDidChangeSoftWrapped(softWrapped => {if (softWrapped !== enforcedSoftWrap) {// Reset the overridden softWrap to `false` once the operation completes. | ||
process.nextTick(() => {if (!editor.isDestroyed()) {editor.setSoftWrapped(enforcedSoftWrap);}});}});} /** | ||
* Small wrapper around `atom.workspace.observeTextEditors` that filters out | ||
* uninitialized remote editors. Most callers should use this one instead. | ||
*/function observeTextEditors(callback) {// The one place where atom.workspace.observeTextEditors needs to be used. | ||
// eslint-disable-next-line rulesdir/atom-apis | ||
return atom.workspace.observeTextEditors(editor => {if (isValidTextEditor(editor)) {callback(editor);}});} /** | ||
* Checks if an object (typically an Atom pane) is a TextEditor with a non-broken path. | ||
*/function isValidTextEditor(item) {// eslint-disable-next-line rulesdir/atom-apis | ||
if (atom.workspace.isTextEditor(item)) {return !(_nuclideUri || _load_nuclideUri()).default.isBrokenDeserializedUri(item.getPath());}return false;}function centerScrollToBufferLine(textEditorElement, bufferLineNumber) {const textEditor = textEditorElement.getModel();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;textEditorElement.setScrollTop(Math.max(scrollTop, 1));textEditorElement.focus();textEditor.setCursorBufferPosition([bufferLineNumber, 0], { autoscroll: false });}function getNonWordCharacters(editor, position) {if ((_semver || _load_semver()).default.gte(atom.getVersion(), '1.24.0-beta0')) {return editor.getNonWordCharacters(position);} else {// This used to take a scope descriptor. | ||
const scope = position == null ? null : editor.scopeDescriptorForBufferPosition(position);return editor.getNonWordCharacters(scope);}} |
@@ -1,322 +0,382 @@ | ||
'use strict'; | ||
'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.__TEST__ = exports.TextEventDispatcher = undefined;exports. | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.__TEST__ = exports.TextEventDispatcher = undefined; | ||
exports.observeTextEditorEvents = observeTextEditorEvents; | ||
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'); | ||
} | ||
var _UniversalDisposable; | ||
function _load_UniversalDisposable() { | ||
return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable')); | ||
} | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
// A reload changes the text in the buffer, so it should trigger a refresh. | ||
/** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/ | ||
const FILE_CHANGE_EVENTS = ['did-change', 'did-reload', 'did-open']; | ||
// A reload basically indicates that an external program saved the file, so | ||
// it should trigger a refresh. | ||
const FILE_SAVE_EVENTS = ['did-save', 'did-reload', 'did-open']; | ||
/** | ||
* Stores callbacks keyed on grammar and event, to allow for easy retrieval when | ||
* we need to dispatch to all callbacks registered for a given (grammar, event) | ||
* pair. | ||
*/ | ||
class TextCallbackContainer { | ||
// grammar -> event -> callback | ||
// invariant: no empty maps or sets (they should be removed instead) | ||
constructor() { | ||
this._callbacks = new Map(); | ||
this._allGrammarCallbacks = new Map(); | ||
} | ||
// 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 resultSet = new Set(); | ||
const add = callback => { | ||
resultSet.add(callback); | ||
}; | ||
callbacksForGrammar.forEach(add); | ||
callbacksForAll.forEach(add); | ||
return resultSet; | ||
} | ||
isEmpty() { | ||
return this._callbacks.size === 0 && this._allGrammarCallbacks.size === 0; | ||
} | ||
_getCallbacksFromEventMap(eventMap, event) { | ||
if (!eventMap) { | ||
return new Set(); | ||
} | ||
const callbackSet = eventMap.get(event); | ||
if (!callbackSet) { | ||
return new Set(); | ||
} | ||
return callbackSet; | ||
} | ||
addCallback(grammarScopes, events, callback) { | ||
if (grammarScopes === 'all') { | ||
this._addToEventMap(this._allGrammarCallbacks, events, callback); | ||
} else { | ||
for (const grammarScope of grammarScopes) { | ||
let eventMap = this._callbacks.get(grammarScope); | ||
if (!eventMap) { | ||
eventMap = new Map(); | ||
this._callbacks.set(grammarScope, eventMap); | ||
} | ||
this._addToEventMap(eventMap, events, callback); | ||
} | ||
} | ||
} | ||
// remove the callbacks, maintaining the invariant that there should be no | ||
// empty maps or sets in this._callbacks | ||
removeCallback(grammarScopes, events, callback) { | ||
if (grammarScopes === 'all') { | ||
this._removeFromEventMap(this._allGrammarCallbacks, events, callback); | ||
} else { | ||
for (const grammarScope of grammarScopes) { | ||
const eventMap = this._callbacks.get(grammarScope); | ||
if (!eventMap) { | ||
throw new Error('Invariant violation: "eventMap"'); | ||
} | ||
this._removeFromEventMap(eventMap, events, callback); | ||
if (eventMap.size === 0) { | ||
this._callbacks.delete(grammarScope); | ||
} | ||
} | ||
} | ||
} | ||
_addToEventMap(eventMap, events, callback) { | ||
for (const event of events) { | ||
let callbackSet = eventMap.get(event); | ||
if (!callbackSet) { | ||
callbackSet = new Set(); | ||
eventMap.set(event, callbackSet); | ||
} | ||
callbackSet.add(callback); | ||
} | ||
} | ||
_removeFromEventMap(eventMap, events, callback) { | ||
for (const event of events) { | ||
const callbackSet = eventMap.get(event); | ||
if (!callbackSet) { | ||
throw new Error('Invariant violation: "callbackSet"'); | ||
} | ||
callbackSet.delete(callback); | ||
if (callbackSet.size === 0) { | ||
eventMap.delete(event); | ||
} | ||
} | ||
} | ||
} | ||
/** | ||
* Meant to make it simple and easy for a DiagnosticProvider to subscribe to | ||
* relevant events. Currently provides two methods, onFileChange and onFileSave. | ||
* A DiagnosticProvider will typically subscribe to only one, depending on | ||
* whether it wants to be notified whenever a file changes or only when it is | ||
* saved. | ||
* | ||
* Both methods take two arguments: | ||
* - An Iterable of grammars for which the DiagnosticProvider can provide | ||
* diagnostics. | ||
* - The callback to be called on a text event. | ||
* | ||
* A TextEventDispatcher will be subscribed to text events if and only if it has | ||
* subscribers of its own. If all subscribers unsubscribe, it will unsubscribe | ||
* from Atom's text events. | ||
* | ||
*/ | ||
class TextEventDispatcher { | ||
constructor() { | ||
this._callbackContainer = new TextCallbackContainer(); | ||
this._editorListenerDisposable = null; | ||
this._pendingEvents = new WeakMap(); | ||
} | ||
_onEvents(grammarScopes, events, callback) { | ||
if (this._callbackContainer.isEmpty()) { | ||
this._registerEditorListeners(); | ||
} | ||
// Sometimes these events get triggered several times in succession | ||
// (particularly on startup). | ||
const debouncedCallback = (0, (_debounce || _load_debounce()).default)(callback, 50, true); | ||
this._callbackContainer.addCallback(grammarScopes, events, debouncedCallback); | ||
const disposables = new (_UniversalDisposable || _load_UniversalDisposable()).default(() => { | ||
this._callbackContainer.removeCallback(grammarScopes, events, debouncedCallback); | ||
if (this._callbackContainer.isEmpty()) { | ||
this._deregisterEditorListeners(); | ||
} | ||
}); | ||
return disposables; | ||
} | ||
onFileChange(grammarScopes, callback) { | ||
return this._onEvents(grammarScopes, FILE_CHANGE_EVENTS, callback); | ||
} | ||
onAnyFileChange(callback) { | ||
return this._onEvents('all', FILE_CHANGE_EVENTS, callback); | ||
} | ||
onFileSave(grammarScopes, callback) { | ||
return this._onEvents(grammarScopes, FILE_SAVE_EVENTS, callback); | ||
} | ||
onAnyFileSave(callback) { | ||
return this._onEvents('all', FILE_SAVE_EVENTS, callback); | ||
} | ||
_registerEditorListeners() { | ||
if (!this._editorListenerDisposable) { | ||
this._editorListenerDisposable = new (_UniversalDisposable || _load_UniversalDisposable()).default(); | ||
} | ||
// Whenever the active pane item changes, we check to see if there are any | ||
// 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((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')); | ||
})); | ||
} | ||
_deregisterEditorListeners() { | ||
if (this._editorListenerDisposable) { | ||
this._getEditorListenerDisposable().dispose(); | ||
this._editorListenerDisposable = null; | ||
} | ||
} | ||
_dispatchEvents(editor, event) { | ||
const currentEditor = atom.workspace.getActiveTextEditor(); | ||
if (currentEditor && editor === currentEditor) { | ||
const callbacks = this._callbackContainer.getCallbacks(editor.getGrammar().scopeName, event); | ||
for (const callback of callbacks) { | ||
callback(editor); | ||
} | ||
// We want to avoid storing pending events if this event was generated by | ||
// the same buffer as the current editor, to avoid duplicating events when | ||
// multiple panes have the same file open. | ||
} else if (!currentEditor || editor.getBuffer() !== currentEditor.getBuffer()) { | ||
// Trigger this event next time we switch to an editor with this buffer. | ||
const buffer = editor.getBuffer(); | ||
let events = this._pendingEvents.get(buffer); | ||
if (!events) { | ||
events = new Set(); | ||
this._pendingEvents.set(buffer, events); | ||
} | ||
events.add(event); | ||
} | ||
} | ||
_getEditorListenerDisposable() { | ||
const disposable = this._editorListenerDisposable; | ||
if (!disposable) { | ||
throw new Error('TextEventDispatcher disposable is not initialized'); | ||
} | ||
return disposable; | ||
} | ||
} | ||
exports.TextEventDispatcher = TextEventDispatcher; | ||
function observeTextEditorEvents(grammarScopes, events) { | ||
return _rxjsBundlesRxMinJs.Observable.defer(() => { | ||
const dispatcher = new TextEventDispatcher(); | ||
if (events === 'changes') { | ||
if (grammarScopes === 'all') { | ||
return (0, (_event || _load_event()).observableFromSubscribeFunction)(cb => dispatcher.onAnyFileChange(cb)); | ||
} else { | ||
return (0, (_event || _load_event()).observableFromSubscribeFunction)(cb => dispatcher.onFileChange(grammarScopes, cb)); | ||
} | ||
} else { | ||
if (grammarScopes === 'all') { | ||
return (0, (_event || _load_event()).observableFromSubscribeFunction)(cb => dispatcher.onAnyFileSave(cb)); | ||
} else { | ||
return (0, (_event || _load_event()).observableFromSubscribeFunction)(cb => dispatcher.onFileSave(grammarScopes, cb)); | ||
} | ||
} | ||
}); | ||
} | ||
const __TEST__ = exports.__TEST__ = { | ||
TextCallbackContainer | ||
}; | ||
observeTextEditorEvents = observeTextEditorEvents;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');}var _UniversalDisposable;function _load_UniversalDisposable() {return _UniversalDisposable = _interopRequireDefault(require('nuclide-commons/UniversalDisposable'));}function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };} // A reload changes the text in the buffer, so it should trigger a refresh. | ||
/** | ||
* Copyright (c) 2017-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* | ||
* @format | ||
*/const FILE_CHANGE_EVENTS = ['did-change', 'did-reload', 'did-open']; // A reload basically indicates that an external program saved the file, so | ||
// it should trigger a refresh. | ||
const FILE_SAVE_EVENTS = ['did-save', 'did-reload', 'did-open']; /** | ||
* Stores callbacks keyed on grammar and event, to allow for easy retrieval when | ||
* we need to dispatch to all callbacks registered for a given (grammar, event) | ||
* pair. | ||
*/class TextCallbackContainer {// grammar -> event -> callback | ||
// invariant: no empty maps or sets (they should be removed instead) | ||
constructor() {this._callbacks = new Map();this._allGrammarCallbacks = new Map();} // 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 resultSet = new Set();const add = callback => {resultSet.add(callback);};callbacksForGrammar.forEach(add);callbacksForAll.forEach(add);return resultSet;}isEmpty() {return this._callbacks.size === 0 && this._allGrammarCallbacks.size === 0;}_getCallbacksFromEventMap(eventMap, event) {if (!eventMap) {return new Set();}const callbackSet = eventMap.get(event);if (!callbackSet) {return new Set();}return callbackSet;}addCallback(grammarScopes, events, callback) {if (grammarScopes === 'all') {this._addToEventMap(this._allGrammarCallbacks, events, callback);} else {for (const grammarScope of grammarScopes) {let eventMap = this._callbacks.get(grammarScope);if (!eventMap) {eventMap = new Map();this._callbacks.set(grammarScope, eventMap);}this._addToEventMap(eventMap, events, callback);}}} // remove the callbacks, maintaining the invariant that there should be no | ||
// empty maps or sets in this._callbacks | ||
removeCallback(grammarScopes, events, callback) {if (grammarScopes === 'all') {this._removeFromEventMap(this._allGrammarCallbacks, events, callback);} else {for (const grammarScope of grammarScopes) {const eventMap = this._callbacks.get(grammarScope);if (!eventMap) {throw new Error('Invariant violation: "eventMap"');}this._removeFromEventMap(eventMap, events, callback);if (eventMap.size === 0) {this._callbacks.delete(grammarScope);}}}}_addToEventMap(eventMap, events, callback) {for (const event of events) {let callbackSet = eventMap.get(event);if (!callbackSet) {callbackSet = new Set();eventMap.set(event, callbackSet);}callbackSet.add(callback);}}_removeFromEventMap(eventMap, events, callback) {for (const event of events) {const callbackSet = eventMap.get(event);if (!callbackSet) {throw new Error('Invariant violation: "callbackSet"');}callbackSet.delete(callback);if (callbackSet.size === 0) {eventMap.delete(event);}}}} /** | ||
* Meant to make it simple and easy for a DiagnosticProvider to subscribe to | ||
* relevant events. Currently provides two methods, onFileChange and onFileSave. | ||
* A DiagnosticProvider will typically subscribe to only one, depending on | ||
* whether it wants to be notified whenever a file changes or only when it is | ||
* saved. | ||
* | ||
* Both methods take two arguments: | ||
* - An Iterable of grammars for which the DiagnosticProvider can provide | ||
* diagnostics. | ||
* - The callback to be called on a text event. | ||
* | ||
* A TextEventDispatcher will be subscribed to text events if and only if it has | ||
* subscribers of its own. If all subscribers unsubscribe, it will unsubscribe | ||
* from Atom's text events. | ||
* | ||
*/class TextEventDispatcher {constructor() {this._callbackContainer = new TextCallbackContainer();this._editorListenerDisposable = null;this._pendingEvents = new WeakMap();}_onEvents(grammarScopes, events, callback) {if (this._callbackContainer.isEmpty()) {this._registerEditorListeners();} // Sometimes these events get triggered several times in succession | ||
// (particularly on startup). | ||
const debouncedCallback = (0, (_debounce || _load_debounce()).default)(callback, 50, true);this._callbackContainer.addCallback(grammarScopes, events, debouncedCallback);const disposables = new (_UniversalDisposable || _load_UniversalDisposable()).default(() => {this._callbackContainer.removeCallback(grammarScopes, events, debouncedCallback);if (this._callbackContainer.isEmpty()) {this._deregisterEditorListeners();}});return disposables;}onFileChange(grammarScopes, callback) {return this._onEvents(grammarScopes, FILE_CHANGE_EVENTS, callback);}onAnyFileChange(callback) {return this._onEvents('all', FILE_CHANGE_EVENTS, callback);}onFileSave(grammarScopes, callback) {return this._onEvents(grammarScopes, FILE_SAVE_EVENTS, callback);}onAnyFileSave(callback) {return this._onEvents('all', FILE_SAVE_EVENTS, callback);}_registerEditorListeners() {if (!this._editorListenerDisposable) {this._editorListenerDisposable = new (_UniversalDisposable || _load_UniversalDisposable()).default();} // Whenever the active pane item changes, we check to see if there are any | ||
// 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((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'));}));}_deregisterEditorListeners() {if (this._editorListenerDisposable) {this._getEditorListenerDisposable().dispose();this._editorListenerDisposable = null;}}_dispatchEvents(editor, event) {const currentEditor = atom.workspace.getActiveTextEditor();if (currentEditor && editor === currentEditor) {const callbacks = this._callbackContainer.getCallbacks(editor.getGrammar().scopeName, event);for (const callback of callbacks) {callback(editor);} // We want to avoid storing pending events if this event was generated by | ||
// the same buffer as the current editor, to avoid duplicating events when | ||
// multiple panes have the same file open. | ||
} else if (!currentEditor || editor.getBuffer() !== currentEditor.getBuffer()) {// Trigger this event next time we switch to an editor with this buffer. | ||
const buffer = editor.getBuffer();let events = this._pendingEvents.get(buffer);if (!events) {events = new Set();this._pendingEvents.set(buffer, events);}events.add(event);}}_getEditorListenerDisposable() {const disposable = this._editorListenerDisposable;if (!disposable) {throw new Error('TextEventDispatcher disposable is not initialized');}return disposable;}}exports.TextEventDispatcher = TextEventDispatcher;function observeTextEditorEvents(grammarScopes, events) {return _rxjsBundlesRxMinJs.Observable.defer(() => {const dispatcher = new TextEventDispatcher();if (events === 'changes') {if (grammarScopes === 'all') {return (0, (_event || _load_event()).observableFromSubscribeFunction)(cb => dispatcher.onAnyFileChange(cb));} else {return (0, (_event || _load_event()).observableFromSubscribeFunction)(cb => dispatcher.onFileChange(grammarScopes, cb));}} else {if (grammarScopes === 'all') {return (0, (_event || _load_event()).observableFromSubscribeFunction)(cb => dispatcher.onAnyFileSave(cb));} else {return (0, (_event || _load_event()).observableFromSubscribeFunction)(cb => dispatcher.onFileSave(grammarScopes, cb));}}});}const __TEST__ = exports.__TEST__ = { TextCallbackContainer }; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 8 instances in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 3 instances in 1 package
320972
62
21
1843
1
+ Addednuclide-commons@0.7.1(transitive)
- Removednuclide-commons@0.7.0(transitive)
Updatednuclide-commons@0.7.1