diff options
| author | Ben Beltran <ben@nsovocal.com> | 2015-07-10 11:12:25 -0500 |
|---|---|---|
| committer | Ben Beltran <ben@nsovocal.com> | 2015-07-10 11:12:25 -0500 |
| commit | 24c7594d62d8d7fbbcdb64b11ce4adc5d8e6991a (patch) | |
| tree | ded312222bb108923da1820ba40b04d710d20e5b /atom/packages/ex-mode/node_modules/atom-space-pen-views | |
| parent | eb786e82d170e2abc351a432ade616d6ecdeeb6b (diff) | |
Adds atom
Diffstat (limited to 'atom/packages/ex-mode/node_modules/atom-space-pen-views')
15 files changed, 1305 insertions, 0 deletions
diff --git a/atom/packages/ex-mode/node_modules/atom-space-pen-views/LICENSE.md b/atom/packages/ex-mode/node_modules/atom-space-pen-views/LICENSE.md new file mode 100644 index 0000000..4d231b4 --- /dev/null +++ b/atom/packages/ex-mode/node_modules/atom-space-pen-views/LICENSE.md @@ -0,0 +1,20 @@ +Copyright (c) 2014 GitHub Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/atom/packages/ex-mode/node_modules/atom-space-pen-views/README.md b/atom/packages/ex-mode/node_modules/atom-space-pen-views/README.md new file mode 100644 index 0000000..4f8b31a --- /dev/null +++ b/atom/packages/ex-mode/node_modules/atom-space-pen-views/README.md @@ -0,0 +1,215 @@ +# Atom SpacePen Views [](https://travis-ci.org/atom/atom-space-pen-views) + +This library contains SpacePen views that used to be provided as part of Atom +Core. `TextEditorView`, `SelectListView`, and `ScrollView` exports from the +`atom` module are now deprecated will soon be removed, but can still be used in +packages by depending on this library in your `package.json`. + +## TextEditorView + +A text editor can now be created in Atom by inserting an `<atom-text-editor>` +tag in any location you want an editor. However, if you still want to use the +SpacePen view in order to conveniently convert packages off the deprecated +export, you can use this class. + +### Example + +```coffee +{View} = require 'space-pen' +{TextEditorView} = require 'atom-space-pen-views' + +class MyView extends View + @content: -> + @div => + @div "Type your answer:" + @subview 'answer', new TextEditorView(mini: true) +``` + +### Constructor Params + +Pass an optional params object to the constructor with the following keys: + +* `mini` If `true`, will construct a single-line editor for use as an input + field. +* `placeholderText` A string of placeholder text to appear in the editor when + empty + +### Methods + +#### `::getModel` + +Returns the underlying `TextEditor` model instance. + +## ScrollView + + Handles several core events to update scroll position: + + * `core:move-up` Scrolls the view up + * `core:move-down` Scrolls the view down + * `core:page-up` Scrolls the view up by the height of the page + * `core:page-down` Scrolls the view down by the height of the page + * `core:move-to-top` Scrolls the editor to the top + * `core:move-to-bottom` Scroll the editor to the bottom + + Subclasses must call `super` if overriding the `initialize` method. + +### Example + + ```coffee + {ScrollView} = require 'atom-space-pen-views' + + class MyView extends ScrollView + @content: -> + @div() + + initialize: -> + super + @text('super long content that will scroll') + ``` + +## SelectListView + +Essential: Provides a view that renders a list of items with an editor that +filters the items. Used by many packages such as the fuzzy-finder, +command-palette, symbols-view and autocomplete. + + +### Example + +```coffee +{SelectListView} = require 'atom-space-pen-views' + +class MySelectListView extends SelectListView + initialize: -> + super + @addClass('overlay from-top') + @setItems(['Hello', 'World']) + atom.workspaceView.append(this) + @focusFilterEditor() + + viewForItem: (item) -> + "<li>#{item}</li>" + + confirmed: (item) -> + console.log("#{item} was selected") +``` + +## Methods + +### Subclasses Must Implement + +#### `::viewForItem` + +Create a view for the given model item. This method must be overridden by +subclasses. Called when the item is about to appended to the list view. + +* `item` The model item being rendered. This will always be one of the items + previously passed to `::setItems`. + +Returns a String of HTML, DOM element, jQuery object, or View. + +#### `::confirmed` + +Callback function for when an item is selected. This method must +be overridden by subclasses. + +* `item` The selected model item. This will always be one of the items + previously passed to `::setItems`. + +Returns a DOM element, jQuery object, or {View}. + +### Managing the list of items + +#### `::setItems` + +Set the array of items to display in the list. This should be +model items, not actual views. `::viewForItem` will be called to render the +item when it is being appended to the list view. + +* `items` The array of model items to display in the list (default: []). + +#### `::getSelectedItem` + +Get the model item that is currently selected in the list view. + +#### `::getFilterKey` + +Get the property name to use when filtering items. + +This method may be overridden by classes to allow fuzzy filtering based +on a specific property of the item objects. + +For example if the objects you pass to {::setItems} are of the type +`{"id": 3, "name": "Atom"}` then you would return `"name"` from this method +to fuzzy filter by that property when text is entered into this view's +editor. + + +#### `::getFilterQuery` + +Get the filter query to use when fuzzy filtering the visible elements. + +By default this method returns the text in the mini editor but it can be +overridden by subclasses if needed. + +Returns a {String} to use when fuzzy filtering the elements to display. + + +#### `::setMaxItems` + +Set the maximum numbers of items to display in the list. + +This should be called before `setItems` is called or else the first time the +list displays it will include all the items. + +* `maxItems` The maximum {Number} of items to display. + +#### `::populateList` + +Extended: Populate the list view with the model items previously set by calling +{::setItems}. + +Subclasses may override this method but should always call `super`. + +### Messages + +#### `::setError` + +Set the error message to display. + +* `message` A string with an error message (default: ''). + +#### `::setLoading` + +Set the loading message to display. + +* `message` A string with a loading message (default: ''). + +#### `::getEmptyMessage` + +Get the message to display when there are no items. + +Subclasses may override this method to customize the message. + +* `itemCount` The {Number} of items in the array specified to {::setItems} +* `filteredItemCount` The {Number} of items that pass the fuzzy filter test. + +Returns a {String} message (default: 'No matches found'). + +### View Actions + +#### `::cancel` + +Cancel and close this select list view. + +This restores focus to the previously focused element if `::storeFocusedElement` +was called prior to this view being attached. + +#### `::focusFilterEditor` + +Focus the fuzzy filter editor view. + +#### `::storeFocusedElement` + +Store the currently focused element. This element will be given back focus when +`::cancel` is called. diff --git a/atom/packages/ex-mode/node_modules/atom-space-pen-views/lib/main.js b/atom/packages/ex-mode/node_modules/atom-space-pen-views/lib/main.js new file mode 100644 index 0000000..ebdf364 --- /dev/null +++ b/atom/packages/ex-mode/node_modules/atom-space-pen-views/lib/main.js @@ -0,0 +1,22 @@ +(function() { + var $, $$, $$$, View, jQuery, _ref; + + _ref = require('space-pen'), View = _ref.View, jQuery = _ref.jQuery, $ = _ref.$, $$ = _ref.$$, $$$ = _ref.$$$; + + exports.View = View; + + exports.jQuery = jQuery; + + exports.$ = $; + + exports.$$ = $$; + + exports.$$$ = $$$; + + exports.TextEditorView = require('./text-editor-view'); + + exports.SelectListView = require('./select-list-view'); + + exports.ScrollView = require('./scroll-view'); + +}).call(this); diff --git a/atom/packages/ex-mode/node_modules/atom-space-pen-views/lib/scroll-view.js b/atom/packages/ex-mode/node_modules/atom-space-pen-views/lib/scroll-view.js new file mode 100644 index 0000000..b77ad49 --- /dev/null +++ b/atom/packages/ex-mode/node_modules/atom-space-pen-views/lib/scroll-view.js @@ -0,0 +1,54 @@ +(function() { + var ScrollView, View, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + View = require('space-pen').View; + + module.exports = ScrollView = (function(_super) { + __extends(ScrollView, _super); + + function ScrollView() { + return ScrollView.__super__.constructor.apply(this, arguments); + } + + ScrollView.prototype.initialize = function() { + return atom.commands.add(this.element, { + 'core:move-up': (function(_this) { + return function() { + return _this.scrollUp(); + }; + })(this), + 'core:move-down': (function(_this) { + return function() { + return _this.scrollDown(); + }; + })(this), + 'core:page-up': (function(_this) { + return function() { + return _this.pageUp(); + }; + })(this), + 'core:page-down': (function(_this) { + return function() { + return _this.pageDown(); + }; + })(this), + 'core:move-to-top': (function(_this) { + return function() { + return _this.scrollToTop(); + }; + })(this), + 'core:move-to-bottom': (function(_this) { + return function() { + return _this.scrollToBottom(); + }; + })(this) + }); + }; + + return ScrollView; + + })(View); + +}).call(this); diff --git a/atom/packages/ex-mode/node_modules/atom-space-pen-views/lib/select-list-view.js b/atom/packages/ex-mode/node_modules/atom-space-pen-views/lib/select-list-view.js new file mode 100644 index 0000000..152702a --- /dev/null +++ b/atom/packages/ex-mode/node_modules/atom-space-pen-views/lib/select-list-view.js @@ -0,0 +1,361 @@ +(function() { + var $, SelectListView, TextEditorView, View, fuzzyFilter, _ref, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + _ref = require('space-pen'), $ = _ref.$, View = _ref.View; + + TextEditorView = require('./text-editor-view'); + + fuzzyFilter = null; + + atom.themes.requireStylesheet(require.resolve('../stylesheets/select-list.less')); + + module.exports = SelectListView = (function(_super) { + __extends(SelectListView, _super); + + function SelectListView() { + return SelectListView.__super__.constructor.apply(this, arguments); + } + + SelectListView.content = function() { + return this.div({ + "class": 'select-list' + }, (function(_this) { + return function() { + _this.subview('filterEditorView', new TextEditorView({ + mini: true + })); + _this.div({ + "class": 'error-message', + outlet: 'error' + }); + _this.div({ + "class": 'loading', + outlet: 'loadingArea' + }, function() { + _this.span({ + "class": 'loading-message', + outlet: 'loading' + }); + return _this.span({ + "class": 'badge', + outlet: 'loadingBadge' + }); + }); + return _this.ol({ + "class": 'list-group', + outlet: 'list' + }); + }; + })(this)); + }; + + SelectListView.prototype.maxItems = Infinity; + + SelectListView.prototype.scheduleTimeout = null; + + SelectListView.prototype.inputThrottle = 50; + + SelectListView.prototype.cancelling = false; + + + /* + Section: Construction + */ + + SelectListView.prototype.initialize = function() { + this.filterEditorView.getModel().getBuffer().onDidChange((function(_this) { + return function() { + return _this.schedulePopulateList(); + }; + })(this)); + this.filterEditorView.on('blur', (function(_this) { + return function(e) { + if (!_this.cancelling) { + return _this.cancel(); + } + }; + })(this)); + atom.commands.add(this.element, { + 'core:move-up': (function(_this) { + return function(event) { + _this.selectPreviousItemView(); + return event.stopPropagation(); + }; + })(this), + 'core:move-down': (function(_this) { + return function(event) { + _this.selectNextItemView(); + return event.stopPropagation(); + }; + })(this), + 'core:move-to-top': (function(_this) { + return function(event) { + _this.selectItemView(_this.list.find('li:first')); + _this.list.scrollToTop(); + return event.stopPropagation(); + }; + })(this), + 'core:move-to-bottom': (function(_this) { + return function(event) { + _this.selectItemView(_this.list.find('li:last')); + _this.list.scrollToBottom(); + return event.stopPropagation(); + }; + })(this), + 'core:confirm': (function(_this) { + return function(event) { + _this.confirmSelection(); + return event.stopPropagation(); + }; + })(this), + 'core:cancel': (function(_this) { + return function(event) { + _this.cancel(); + return event.stopPropagation(); + }; + })(this) + }); + this.list.on('mousedown', (function(_this) { + return function(_arg) { + var target; + target = _arg.target; + if (target === _this.list[0]) { + return false; + } + }; + })(this)); + this.list.on('mousedown', 'li', (function(_this) { + return function(e) { + _this.selectItemView($(e.target).closest('li')); + e.preventDefault(); + return false; + }; + })(this)); + return this.list.on('mouseup', 'li', (function(_this) { + return function(e) { + if ($(e.target).closest('li').hasClass('selected')) { + _this.confirmSelection(); + } + e.preventDefault(); + return false; + }; + })(this)); + }; + + + /* + Section: Methods that must be overridden + */ + + SelectListView.prototype.viewForItem = function(item) { + throw new Error("Subclass must implement a viewForItem(item) method"); + }; + + SelectListView.prototype.confirmed = function(item) { + throw new Error("Subclass must implement a confirmed(item) method"); + }; + + + /* + Section: Managing the list of items + */ + + SelectListView.prototype.setItems = function(items) { + this.items = items != null ? items : []; + this.populateList(); + return this.setLoading(); + }; + + SelectListView.prototype.getSelectedItem = function() { + return this.getSelectedItemView().data('select-list-item'); + }; + + SelectListView.prototype.getFilterKey = function() {}; + + SelectListView.prototype.getFilterQuery = function() { + return this.filterEditorView.getText(); + }; + + SelectListView.prototype.setMaxItems = function(maxItems) { + this.maxItems = maxItems; + }; + + SelectListView.prototype.populateList = function() { + var filterQuery, filteredItems, i, item, itemView, _i, _ref1; + if (this.items == null) { + return; + } + filterQuery = this.getFilterQuery(); + if (filterQuery.length) { + if (fuzzyFilter == null) { + fuzzyFilter = require('fuzzaldrin').filter; + } + filteredItems = fuzzyFilter(this.items, filterQuery, { + key: this.getFilterKey() + }); + } else { + filteredItems = this.items; + } + this.list.empty(); + if (filteredItems.length) { + this.setError(null); + for (i = _i = 0, _ref1 = Math.min(filteredItems.length, this.maxItems); 0 <= _ref1 ? _i < _ref1 : _i > _ref1; i = 0 <= _ref1 ? ++_i : --_i) { + item = filteredItems[i]; + itemView = $(this.viewForItem(item)); + itemView.data('select-list-item', item); + this.list.append(itemView); + } + return this.selectItemView(this.list.find('li:first')); + } else { + return this.setError(this.getEmptyMessage(this.items.length, filteredItems.length)); + } + }; + + + /* + Section: Messages to the user + */ + + SelectListView.prototype.setError = function(message) { + if (message == null) { + message = ''; + } + if (message.length === 0) { + return this.error.text('').hide(); + } else { + this.setLoading(); + return this.error.text(message).show(); + } + }; + + SelectListView.prototype.setLoading = function(message) { + if (message == null) { + message = ''; + } + if (message.length === 0) { + this.loading.text(""); + this.loadingBadge.text(""); + return this.loadingArea.hide(); + } else { + this.setError(); + this.loading.text(message); + return this.loadingArea.show(); + } + }; + + SelectListView.prototype.getEmptyMessage = function(itemCount, filteredItemCount) { + return 'No matches found'; + }; + + + /* + Section: View Actions + */ + + SelectListView.prototype.cancel = function() { + var filterEditorViewFocused; + this.list.empty(); + this.cancelling = true; + filterEditorViewFocused = this.filterEditorView.hasFocus(); + if (typeof this.cancelled === "function") { + this.cancelled(); + } + this.filterEditorView.setText(''); + if (filterEditorViewFocused) { + this.restoreFocus(); + } + this.cancelling = false; + return clearTimeout(this.scheduleTimeout); + }; + + SelectListView.prototype.focusFilterEditor = function() { + return this.filterEditorView.focus(); + }; + + SelectListView.prototype.storeFocusedElement = function() { + return this.previouslyFocusedElement = $(document.activeElement); + }; + + + /* + Section: Private + */ + + SelectListView.prototype.selectPreviousItemView = function() { + var view; + view = this.getSelectedItemView().prev(); + if (!view.length) { + view = this.list.find('li:last'); + } + return this.selectItemView(view); + }; + + SelectListView.prototype.selectNextItemView = function() { + var view; + view = this.getSelectedItemView().next(); + if (!view.length) { + view = this.list.find('li:first'); + } + return this.selectItemView(view); + }; + + SelectListView.prototype.selectItemView = function(view) { + if (!view.length) { + return; + } + this.list.find('.selected').removeClass('selected'); + view.addClass('selected'); + return this.scrollToItemView(view); + }; + + SelectListView.prototype.scrollToItemView = function(view) { + var desiredBottom, desiredTop, scrollTop; + scrollTop = this.list.scrollTop(); + desiredTop = view.position().top + scrollTop; + desiredBottom = desiredTop + view.outerHeight(); + if (desiredTop < scrollTop) { + return this.list.scrollTop(desiredTop); + } else if (desiredBottom > this.list.scrollBottom()) { + return this.list.scrollBottom(desiredBottom); + } + }; + + SelectListView.prototype.restoreFocus = function() { + var _ref1; + return (_ref1 = this.previouslyFocusedElement) != null ? _ref1.focus() : void 0; + }; + + SelectListView.prototype.getSelectedItemView = function() { + return this.list.find('li.selected'); + }; + + SelectListView.prototype.confirmSelection = function() { + var item; + item = this.getSelectedItem(); + if (item != null) { + return this.confirmed(item); + } else { + return this.cancel(); + } + }; + + SelectListView.prototype.schedulePopulateList = function() { + var populateCallback; + clearTimeout(this.scheduleTimeout); + populateCallback = (function(_this) { + return function() { + if (_this.isOnDom()) { + return _this.populateList(); + } + }; + })(this); + return this.scheduleTimeout = setTimeout(populateCallback, this.inputThrottle); + }; + + return SelectListView; + + })(View); + +}).call(this); diff --git a/atom/packages/ex-mode/node_modules/atom-space-pen-views/lib/text-editor-view.js b/atom/packages/ex-mode/node_modules/atom-space-pen-views/lib/text-editor-view.js new file mode 100644 index 0000000..e957a2b --- /dev/null +++ b/atom/packages/ex-mode/node_modules/atom-space-pen-views/lib/text-editor-view.js @@ -0,0 +1,63 @@ +(function() { + var $, TextEditorView, View, _ref, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + + _ref = require('space-pen'), View = _ref.View, $ = _ref.$; + + module.exports = TextEditorView = (function(_super) { + __extends(TextEditorView, _super); + + function TextEditorView(params) { + var attributes, mini, name, placeholderText, value; + if (params == null) { + params = {}; + } + mini = params.mini, placeholderText = params.placeholderText, attributes = params.attributes; + if (attributes == null) { + attributes = {}; + } + if (mini != null) { + attributes['mini'] = mini; + } + if (placeholderText != null) { + attributes['placeholder-text'] = placeholderText; + } + this.element = document.createElement('atom-text-editor'); + for (name in attributes) { + value = attributes[name]; + this.element.setAttribute(name, value); + } + if (this.element.__spacePenView != null) { + this.element.__spacePenView = this; + this.element.__allowViewAccess = true; + } + TextEditorView.__super__.constructor.apply(this, arguments); + this.setModel(this.element.getModel()); + } + + TextEditorView.prototype.setModel = function(model) { + this.model = model; + }; + + TextEditorView.prototype.getModel = function() { + return this.model; + }; + + TextEditorView.prototype.getText = function() { + return this.model.getText(); + }; + + TextEditorView.prototype.setText = function(text) { + return this.model.setText(text); + }; + + TextEditorView.prototype.hasFocus = function() { + return this.element.hasFocus(); + }; + + return TextEditorView; + + })(View); + +}).call(this); diff --git a/atom/packages/ex-mode/node_modules/atom-space-pen-views/node_modules/fuzzaldrin/LICENSE.md b/atom/packages/ex-mode/node_modules/atom-space-pen-views/node_modules/fuzzaldrin/LICENSE.md new file mode 100644 index 0000000..fbe20d2 --- /dev/null +++ b/atom/packages/ex-mode/node_modules/atom-space-pen-views/node_modules/fuzzaldrin/LICENSE.md @@ -0,0 +1,21 @@ +Copyright (c) 2009-2011 Joshaven Potter <yourtech@gmail.com> +Copyright (c) 2013 GitHub Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/atom/packages/ex-mode/node_modules/atom-space-pen-views/node_modules/fuzzaldrin/README.md b/atom/packages/ex-mode/node_modules/atom-space-pen-views/node_modules/fuzzaldrin/README.md new file mode 100644 index 0000000..a50867b --- /dev/null +++ b/atom/packages/ex-mode/node_modules/atom-space-pen-views/node_modules/fuzzaldrin/README.md @@ -0,0 +1,77 @@ +# fuzzaldrin + +[](https://travis-ci.org/atom/fuzzaldrin) +[](https://ci.appveyor.com/project/kevinsawicki/fuzzaldrin/branch/master) + +Fuzzy filtering and string scoring. + +This library is used by [Atom](http://atom.io) and so its focus will be on +scoring and filtering paths, methods, and other things common when writing code. +It therefore will specialize in handling common patterns in these types of +strings such as characters like `/`, `-`, and `_`, and also handling of +camel cased text. + +## Using + +```sh +npm install fuzzaldrin +``` + +### filter(candidates, query, [options]) + +Sort and filter the given candidates by matching them against the given query. + +* `candidates` - An array of strings or objects. +* `query` - A string query to match each candidate against. +* `options` - An optional object with the following keys: + * `key` - The property to use for scoring if the candidates are objects. + * `maxResults` - The maximum numbers of results to return. + +Returns an array of candidates sorted by best match against the query. + +```coffee +{filter} = require 'fuzzaldrin' + +# With an array of strings +candidates = ['Call', 'Me', 'Maybe'] +results = filter(candidates, 'me') +console.log(results) # ['Me', 'Maybe'] + +# With an array of objects +candidates = [ + {name: 'Call', id: 1} + {name: 'Me', id: 2} + {name: 'Maybe', id: 3} +] +results = filter(candidates, 'me', key: 'name') +console.log(results) # [{name: 'Me', id: 2}, {name: 'Maybe', id: 3}] +``` + +### score(string, query) + +Score the given string against the given query. + +* `string` - The string the score. +* `query` - The query to score the string against. + +```coffee +{score} = require 'fuzzaldrin' + +score('Me', 'me') # 0.17099999999999999 +score('Maybe', 'me') # 0.0693 +``` + +## Developing + +```sh +git clone https://github.com/atom/fuzzaldrin.git +cd fuzzaldrin +npm install +npm test +``` + +You can run the benchmarks using: + +```sh +npm run benchmark +``` diff --git a/atom/packages/ex-mode/node_modules/atom-space-pen-views/node_modules/fuzzaldrin/lib/filter.js b/atom/packages/ex-mode/node_modules/atom-space-pen-views/node_modules/fuzzaldrin/lib/filter.js new file mode 100644 index 0000000..55d928a --- /dev/null +++ b/atom/packages/ex-mode/node_modules/atom-space-pen-views/node_modules/fuzzaldrin/lib/filter.js @@ -0,0 +1,45 @@ +(function() { + var pluckCandidates, scorer, sortCandidates; + + scorer = require('./scorer'); + + pluckCandidates = function(a) { + return a.candidate; + }; + + sortCandidates = function(a, b) { + return b.score - a.score; + }; + + module.exports = function(candidates, query, queryHasSlashes, _arg) { + var candidate, key, maxResults, score, scoredCandidates, string, _i, _len, _ref; + _ref = _arg != null ? _arg : {}, key = _ref.key, maxResults = _ref.maxResults; + if (query) { + scoredCandidates = []; + for (_i = 0, _len = candidates.length; _i < _len; _i++) { + candidate = candidates[_i]; + string = key != null ? candidate[key] : candidate; + if (!string) { + continue; + } + score = scorer.score(string, query, queryHasSlashes); + if (!queryHasSlashes) { + score = scorer.basenameScore(string, query, score); + } + if (score > 0) { + scoredCandidates.push({ + candidate: candidate, + score: score + }); + } + } + scoredCandidates.sort(sortCandidates); + candidates = scoredCandidates.map(pluckCandidates); + } + if (maxResults != null) { + candidates = candidates.slice(0, maxResults); + } + return candidates; + }; + +}).call(this); diff --git a/atom/packages/ex-mode/node_modules/atom-space-pen-views/node_modules/fuzzaldrin/lib/fuzzaldrin.js b/atom/packages/ex-mode/node_modules/atom-space-pen-views/node_modules/fuzzaldrin/lib/fuzzaldrin.js new file mode 100644 index 0000000..41755d2 --- /dev/null +++ b/atom/packages/ex-mode/node_modules/atom-space-pen-views/node_modules/fuzzaldrin/lib/fuzzaldrin.js @@ -0,0 +1,80 @@ +(function() { + var PathSeparator, SpaceRegex, filter, matcher, scorer; + + scorer = require('./scorer'); + + filter = require('./filter'); + + matcher = require('./matcher'); + + PathSeparator = require('path').sep; + + SpaceRegex = /\ /g; + + module.exports = { + filter: function(candidates, query, options) { + var queryHasSlashes; + if (query) { + queryHasSlashes = query.indexOf(PathSeparator) !== -1; + query = query.replace(SpaceRegex, ''); + } + return filter(candidates, query, queryHasSlashes, options); + }, + score: function(string, query) { + var queryHasSlashes, score; + if (!string) { + return 0; + } + if (!query) { + return 0; + } + if (string === query) { + return 2; + } + queryHasSlashes = query.indexOf(PathSeparator) !== -1; + query = query.replace(SpaceRegex, ''); + score = scorer.score(string, query); + if (!queryHasSlashes) { + score = scorer.basenameScore(string, query, score); + } + return score; + }, + match: function(string, query) { + var baseMatches, index, matches, queryHasSlashes, seen, _i, _ref, _results; + if (!string) { + return []; + } + if (!query) { + return []; + } + if (string === query) { + return (function() { + _results = []; + for (var _i = 0, _ref = string.length; 0 <= _ref ? _i < _ref : _i > _ref; 0 <= _ref ? _i++ : _i--){ _results.push(_i); } + return _results; + }).apply(this); + } + queryHasSlashes = query.indexOf(PathSeparator) !== -1; + query = query.replace(SpaceRegex, ''); + matches = matcher.match(string, query); + if (!queryHasSlashes) { + baseMatches = matcher.basenameMatch(string, query); + matches = matches.concat(baseMatches).sort(function(a, b) { + return a - b; + }); + seen = null; + index = 0; + while (index < matches.length) { + if (index && seen === matches[index]) { + matches.splice(index, 1); + } else { + seen = matches[index]; + index++; + } + } + } + return matches; + } + }; + +}).call(this); diff --git a/atom/packages/ex-mode/node_modules/atom-space-pen-views/node_modules/fuzzaldrin/lib/matcher.js b/atom/packages/ex-mode/node_modules/atom-space-pen-views/node_modules/fuzzaldrin/lib/matcher.js new file mode 100644 index 0000000..57edff4 --- /dev/null +++ b/atom/packages/ex-mode/node_modules/atom-space-pen-views/node_modules/fuzzaldrin/lib/matcher.js @@ -0,0 +1,73 @@ +(function() { + var PathSeparator; + + PathSeparator = require('path').sep; + + exports.basenameMatch = function(string, query) { + var base, index, lastCharacter, slashCount; + index = string.length - 1; + while (string[index] === PathSeparator) { + index--; + } + slashCount = 0; + lastCharacter = index; + base = null; + while (index >= 0) { + if (string[index] === PathSeparator) { + slashCount++; + if (base == null) { + base = string.substring(index + 1, lastCharacter + 1); + } + } else if (index === 0) { + if (lastCharacter < string.length - 1) { + if (base == null) { + base = string.substring(0, lastCharacter + 1); + } + } else { + if (base == null) { + base = string; + } + } + } + index--; + } + return exports.match(base, query, string.length - base.length); + }; + + exports.match = function(string, query, stringOffset) { + var character, indexInQuery, indexInString, lowerCaseIndex, matches, minIndex, queryLength, stringLength, upperCaseIndex, _i, _ref, _results; + if (stringOffset == null) { + stringOffset = 0; + } + if (string === query) { + return (function() { + _results = []; + for (var _i = stringOffset, _ref = stringOffset + string.length; stringOffset <= _ref ? _i < _ref : _i > _ref; stringOffset <= _ref ? _i++ : _i--){ _results.push(_i); } + return _results; + }).apply(this); + } + queryLength = query.length; + stringLength = string.length; + indexInQuery = 0; + indexInString = 0; + matches = []; + while (indexInQuery < queryLength) { + character = query[indexInQuery++]; + lowerCaseIndex = string.indexOf(character.toLowerCase()); + upperCaseIndex = string.indexOf(character.toUpperCase()); + minIndex = Math.min(lowerCaseIndex, upperCaseIndex); + if (minIndex === -1) { + minIndex = Math.max(lowerCaseIndex, upperCaseIndex); + } + indexInString = minIndex; + if (indexInString === -1) { + return []; + } + matches.push(stringOffset + indexInString); + stringOffset += indexInString + 1; + string = string.substring(indexInString + 1, stringLength); + } + return matches; + }; + +}).call(this); diff --git a/atom/packages/ex-mode/node_modules/atom-space-pen-views/node_modules/fuzzaldrin/lib/scorer.js b/atom/packages/ex-mode/node_modules/atom-space-pen-views/node_modules/fuzzaldrin/lib/scorer.js new file mode 100644 index 0000000..c9198ed --- /dev/null +++ b/atom/packages/ex-mode/node_modules/atom-space-pen-views/node_modules/fuzzaldrin/lib/scorer.js @@ -0,0 +1,92 @@ +(function() { + var PathSeparator, queryIsLastPathSegment; + + PathSeparator = require('path').sep; + + exports.basenameScore = function(string, query, score) { + var base, depth, index, lastCharacter, segmentCount, slashCount; + index = string.length - 1; + while (string[index] === PathSeparator) { + index--; + } + slashCount = 0; + lastCharacter = index; + base = null; + while (index >= 0) { + if (string[index] === PathSeparator) { + slashCount++; + if (base == null) { + base = string.substring(index + 1, lastCharacter + 1); + } + } else if (index === 0) { + if (lastCharacter < string.length - 1) { + if (base == null) { + base = string.substring(0, lastCharacter + 1); + } + } else { + if (base == null) { + base = string; + } + } + } + index--; + } + if (base === string) { + score *= 2; + } else if (base) { + score += exports.score(base, query); + } + segmentCount = slashCount + 1; + depth = Math.max(1, 10 - segmentCount); + score *= depth * 0.01; + return score; + }; + + exports.score = function(string, query) { + var character, characterScore, indexInQuery, indexInString, lowerCaseIndex, minIndex, queryLength, queryScore, stringLength, totalCharacterScore, upperCaseIndex, _ref; + if (string === query) { + return 1; + } + if (queryIsLastPathSegment(string, query)) { + return 1; + } + totalCharacterScore = 0; + queryLength = query.length; + stringLength = string.length; + indexInQuery = 0; + indexInString = 0; + while (indexInQuery < queryLength) { + character = query[indexInQuery++]; + lowerCaseIndex = string.indexOf(character.toLowerCase()); + upperCaseIndex = string.indexOf(character.toUpperCase()); + minIndex = Math.min(lowerCaseIndex, upperCaseIndex); + if (minIndex === -1) { + minIndex = Math.max(lowerCaseIndex, upperCaseIndex); + } + indexInString = minIndex; + if (indexInString === -1) { + return 0; + } + characterScore = 0.1; + if (string[indexInString] === character) { + characterScore += 0.1; + } + if (indexInString === 0 || string[indexInString - 1] === PathSeparator) { + characterScore += 0.8; + } else if ((_ref = string[indexInString - 1]) === '-' || _ref === '_' || _ref === ' ') { + characterScore += 0.7; + } + string = string.substring(indexInString + 1, stringLength); + totalCharacterScore += characterScore; + } + queryScore = totalCharacterScore / queryLength; + return ((queryScore * (queryLength / stringLength)) + queryScore) / 2; + }; + + queryIsLastPathSegment = function(string, query) { + if (string[string.length - query.length - 1] === PathSeparator) { + return string.lastIndexOf(query) === string.length - query.length; + } + }; + +}).call(this); diff --git a/atom/packages/ex-mode/node_modules/atom-space-pen-views/node_modules/fuzzaldrin/package.json b/atom/packages/ex-mode/node_modules/atom-space-pen-views/node_modules/fuzzaldrin/package.json new file mode 100644 index 0000000..297615c --- /dev/null +++ b/atom/packages/ex-mode/node_modules/atom-space-pen-views/node_modules/fuzzaldrin/package.json @@ -0,0 +1,71 @@ +{ + "name": "fuzzaldrin", + "version": "2.1.0", + "description": "Fuzzy filtering and string scoring", + "licenses": [ + { + "type": "MIT", + "url": "http://github.com/atom/fuzzaldrin/raw/master/LICENSE.md" + } + ], + "main": "./lib/fuzzaldrin.js", + "scripts": { + "prepublish": "grunt prepublish", + "test": "grunt test", + "benchmark": "coffee benchmark/benchmark.coffee" + }, + "repository": { + "type": "git", + "url": "https://github.com/atom/fuzzaldrin.git" + }, + "bugs": { + "url": "https://github.com/atom/fuzzaldrin/issues" + }, + "homepage": "http://atom.github.io/fuzzaldrin", + "keywords": [ + "fuzzy", + "filter", + "stringscore" + ], + "devDependencies": { + "jasmine-focused": "1.x", + "grunt-contrib-coffee": "~0.9.0", + "grunt-cli": "~0.1.8", + "grunt": "~0.4.1", + "grunt-shell": "~0.2.2", + "grunt-coffeelint": "0.0.6", + "coffee-script": "~1.7" + }, + "_id": "fuzzaldrin@2.1.0", + "dist": { + "shasum": "90204c3e2fdaa6941bb28d16645d418063a90e9b", + "tarball": "http://registry.npmjs.org/fuzzaldrin/-/fuzzaldrin-2.1.0.tgz" + }, + "_from": "fuzzaldrin@>=2.1.0 <3.0.0", + "_npmVersion": "1.4.4", + "_npmUser": { + "name": "kevinsawicki", + "email": "kevinsawicki@gmail.com" + }, + "maintainers": [ + { + "name": "kevinsawicki", + "email": "kevinsawicki@gmail.com" + }, + { + "name": "probablycorey", + "email": "probablycorey@gmail.com" + }, + { + "name": "nathansobo", + "email": "nathansobo@gmail.com" + }, + { + "name": "benogle", + "email": "ogle.ben@gmail.com" + } + ], + "directories": {}, + "_shasum": "90204c3e2fdaa6941bb28d16645d418063a90e9b", + "_resolved": "https://registry.npmjs.org/fuzzaldrin/-/fuzzaldrin-2.1.0.tgz" +} diff --git a/atom/packages/ex-mode/node_modules/atom-space-pen-views/package.json b/atom/packages/ex-mode/node_modules/atom-space-pen-views/package.json new file mode 100644 index 0000000..c5be504 --- /dev/null +++ b/atom/packages/ex-mode/node_modules/atom-space-pen-views/package.json @@ -0,0 +1,71 @@ +{ + "name": "atom-space-pen-views", + "version": "2.0.5", + "description": "Atom SpacePen views that used to live in core.", + "main": "./lib/main", + "scripts": { + "prepublish": "grunt clean lint coffee" + }, + "repository": { + "type": "git", + "url": "https://github.com/atom/atom-space-pen-views.git" + }, + "bugs": { + "url": "https://github.com/atom/atom-space-pen-views/issues" + }, + "licenses": [ + { + "type": "MIT", + "url": "http://github.com/atom/atom-space-pen-views/raw/master/LICENSE.md" + } + ], + "dependencies": { + "fuzzaldrin": "^2.1.0", + "space-pen": "^5.0.1" + }, + "devDependencies": { + "coffee-script": "^1.7.0", + "jasmine-focused": "^1.0.4", + "grunt-contrib-coffee": "^0.9.0", + "grunt-cli": "^0.1.8", + "grunt": "^0.4.1", + "grunt-coffeelint": "^0.0.6", + "rimraf": "^2.2.2", + "coffee-cache": "^0.2.0", + "temp": "^0.6.0" + }, + "gitHead": "0e5fc262cc62d453bbd6dce9ecaec5caddc553f9", + "homepage": "https://github.com/atom/atom-space-pen-views", + "_id": "atom-space-pen-views@2.0.5", + "_shasum": "4ef545a6ef396c8342717b0d9d2569577a2651f4", + "_from": "atom-space-pen-views@>=2.0.4 <3.0.0", + "_npmVersion": "1.4.28", + "_npmUser": { + "name": "kevinsawicki", + "email": "kevinsawicki@gmail.com" + }, + "maintainers": [ + { + "name": "nathansobo", + "email": "nathan@github.com" + }, + { + "name": "benogle", + "email": "ogle.ben@gmail.com" + }, + { + "name": "kevinsawicki", + "email": "kevinsawicki@gmail.com" + }, + { + "name": "maxbrunsfeld", + "email": "maxbrunsfeld@gmail.com" + } + ], + "dist": { + "shasum": "4ef545a6ef396c8342717b0d9d2569577a2651f4", + "tarball": "http://registry.npmjs.org/atom-space-pen-views/-/atom-space-pen-views-2.0.5.tgz" + }, + "directories": {}, + "_resolved": "https://registry.npmjs.org/atom-space-pen-views/-/atom-space-pen-views-2.0.5.tgz" +} diff --git a/atom/packages/ex-mode/node_modules/atom-space-pen-views/stylesheets/select-list.less b/atom/packages/ex-mode/node_modules/atom-space-pen-views/stylesheets/select-list.less new file mode 100644 index 0000000..a9c43b8 --- /dev/null +++ b/atom/packages/ex-mode/node_modules/atom-space-pen-views/stylesheets/select-list.less @@ -0,0 +1,40 @@ +@import "ui-variables"; +@import "octicon-mixins"; + +.select-list { + .loading { + .loading-message { + .octicon(hourglass); + + &:before { + font-size: 1.1em; + width: 1.1em; + height: 1.1em; + margin-right: 5px; + } + } + + .badge { + margin-left: 10px; + } + } + + ol.list-group { + position: relative; + overflow-y: auto; + max-height: 312px; + margin: @component-padding 0 0 0; + padding: 0; + + li { + display: block; + + .primary-line, + .secondary-line { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + } + } + } +} |