nuclide-commons-atom
Advanced tools
Comparing version
@@ -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
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
320972
42.81%62
3.33%1843
-33.3%1
Infinity%+ Added
- Removed
Updated