mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-09-17 14:07:34 +03:00
Merge pull request #664 from pulsar-edit/manual-decaf-bundle
Manual Decaf Bundle (`autocomplete-atom-api`, `autoflow`, `deprecation-cop`) Source
This commit is contained in:
commit
21fedaee87
@ -1,6 +0,0 @@
|
||||
provider = require './provider'
|
||||
|
||||
module.exports =
|
||||
activate: -> provider.load()
|
||||
|
||||
getProvider: -> provider
|
7
packages/autocomplete-atom-api/lib/main.js
Normal file
7
packages/autocomplete-atom-api/lib/main.js
Normal file
@ -0,0 +1,7 @@
|
||||
const provider = require('./provider');
|
||||
|
||||
module.exports = {
|
||||
activate() { return provider.load(); },
|
||||
|
||||
getProvider() { return provider; }
|
||||
};
|
@ -1,97 +0,0 @@
|
||||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
|
||||
CLASSES = require('../completions.json')
|
||||
|
||||
propertyPrefixPattern = /(?:^|\[|\(|,|=|:|\s)\s*(atom\.(?:[a-zA-Z]+\.?){0,2})$/
|
||||
|
||||
module.exports =
|
||||
selector: '.source.coffee, .source.js'
|
||||
filterSuggestions: true
|
||||
|
||||
getSuggestions: ({bufferPosition, editor}) ->
|
||||
return unless @isEditingAnAtomPackageFile(editor)
|
||||
line = editor.getTextInRange([[bufferPosition.row, 0], bufferPosition])
|
||||
@getCompletions(line)
|
||||
|
||||
load: ->
|
||||
@loadCompletions()
|
||||
atom.project.onDidChangePaths => @scanProjectDirectories()
|
||||
@scanProjectDirectories()
|
||||
|
||||
scanProjectDirectories: ->
|
||||
@packageDirectories = []
|
||||
atom.project.getDirectories().forEach (directory) =>
|
||||
return unless directory?
|
||||
@readMetadata directory, (error, metadata) =>
|
||||
if @isAtomPackage(metadata) or @isAtomCore(metadata)
|
||||
@packageDirectories.push(directory)
|
||||
|
||||
readMetadata: (directory, callback) ->
|
||||
fs.readFile path.join(directory.getPath(), 'package.json'), (error, contents) ->
|
||||
unless error?
|
||||
try
|
||||
metadata = JSON.parse(contents)
|
||||
catch parseError
|
||||
error = parseError
|
||||
callback(error, metadata)
|
||||
|
||||
isAtomPackage: (metadata) ->
|
||||
metadata?.engines?.atom?.length > 0
|
||||
|
||||
isAtomCore: (metadata) ->
|
||||
metadata?.name is 'atom'
|
||||
|
||||
isEditingAnAtomPackageFile: (editor) ->
|
||||
editorPath = editor.getPath()
|
||||
if editorPath?
|
||||
parsedPath = path.parse(editorPath)
|
||||
basename = path.basename(parsedPath.dir)
|
||||
if basename is '.atom' or basename is '.pulsar'
|
||||
if parsedPath.base is 'init.coffee' or parsedPath.base is 'init.js'
|
||||
return true
|
||||
for directory in @packageDirectories ? []
|
||||
return true if directory.contains(editorPath)
|
||||
false
|
||||
|
||||
loadCompletions: ->
|
||||
@completions ?= {}
|
||||
@loadProperty('atom', 'AtomEnvironment', CLASSES)
|
||||
|
||||
getCompletions: (line) ->
|
||||
completions = []
|
||||
match = propertyPrefixPattern.exec(line)?[1]
|
||||
return completions unless match
|
||||
|
||||
segments = match.split('.')
|
||||
prefix = segments.pop() ? ''
|
||||
segments = segments.filter (segment) -> segment
|
||||
property = segments[segments.length - 1]
|
||||
propertyCompletions = @completions[property]?.completions ? []
|
||||
for completion in propertyCompletions when not prefix or firstCharsEqual(completion.name, prefix)
|
||||
completions.push(clone(completion))
|
||||
completions
|
||||
|
||||
getPropertyClass: (name) ->
|
||||
atom[name]?.constructor?.name
|
||||
|
||||
loadProperty: (propertyName, className, classes, parent) ->
|
||||
classCompletions = classes[className]
|
||||
return unless classCompletions?
|
||||
|
||||
@completions[propertyName] = completions: []
|
||||
|
||||
for completion in classCompletions
|
||||
@completions[propertyName].completions.push(completion)
|
||||
if completion.type is 'property'
|
||||
propertyClass = @getPropertyClass(completion.name)
|
||||
@loadProperty(completion.name, propertyClass, classes)
|
||||
return
|
||||
|
||||
clone = (obj) ->
|
||||
newObj = {}
|
||||
newObj[k] = v for k, v of obj
|
||||
newObj
|
||||
|
||||
firstCharsEqual = (str1, str2) ->
|
||||
str1[0].toLowerCase() is str2[0].toLowerCase()
|
125
packages/autocomplete-atom-api/lib/provider.js
Normal file
125
packages/autocomplete-atom-api/lib/provider.js
Normal file
@ -0,0 +1,125 @@
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const CLASSES = require('../completions.json');
|
||||
|
||||
const propertyPrefixPattern = /(?:^|\[|\(|,|=|:|\s)\s*(atom\.(?:[a-zA-Z]+\.?){0,2})$/;
|
||||
|
||||
module.exports = {
|
||||
selector: '.source.coffee, .source.js',
|
||||
filterSuggestions: true,
|
||||
|
||||
getSuggestions({bufferPosition, editor}) {
|
||||
if (!this.isEditingAnAtomPackageFile(editor)) { return; }
|
||||
const line = editor.getTextInRange([[bufferPosition.row, 0], bufferPosition]);
|
||||
return this.getCompletions(line);
|
||||
},
|
||||
|
||||
load() {
|
||||
this.loadCompletions();
|
||||
atom.project.onDidChangePaths(() => this.scanProjectDirectories());
|
||||
return this.scanProjectDirectories();
|
||||
},
|
||||
|
||||
scanProjectDirectories() {
|
||||
this.packageDirectories = [];
|
||||
atom.project.getDirectories().forEach(directory => {
|
||||
if (directory == null) { return; }
|
||||
this.readMetadata(directory, (error, metadata) => {
|
||||
if (this.isAtomPackage(metadata) || this.isAtomCore(metadata)) {
|
||||
this.packageDirectories.push(directory);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
readMetadata(directory, callback) {
|
||||
fs.readFile(path.join(directory.getPath(), 'package.json'), function(error, contents) {
|
||||
let metadata;
|
||||
if (error == null) {
|
||||
try {
|
||||
metadata = JSON.parse(contents);
|
||||
} catch (parseError) {
|
||||
error = parseError;
|
||||
}
|
||||
}
|
||||
return callback(error, metadata);
|
||||
});
|
||||
},
|
||||
|
||||
isAtomPackage(metadata) {
|
||||
return metadata?.engines?.atom?.length > 0;
|
||||
},
|
||||
|
||||
isAtomCore(metadata) {
|
||||
return metadata?.name === 'atom';
|
||||
},
|
||||
|
||||
isEditingAnAtomPackageFile(editor) {
|
||||
const editorPath = editor.getPath();
|
||||
if (editorPath != null) {
|
||||
const parsedPath = path.parse(editorPath);
|
||||
const basename = path.basename(parsedPath.dir);
|
||||
if ((basename === '.atom') || (basename === '.pulsar')) {
|
||||
if ((parsedPath.base === 'init.coffee') || (parsedPath.base === 'init.js')) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (let directory of (this.packageDirectories != null ? this.packageDirectories : [])) {
|
||||
if (directory.contains(editorPath)) { return true; }
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
loadCompletions() {
|
||||
if (this.completions == null) { this.completions = {}; }
|
||||
return this.loadProperty('atom', 'AtomEnvironment', CLASSES);
|
||||
},
|
||||
|
||||
getCompletions(line) {
|
||||
const completions = [];
|
||||
const match = propertyPrefixPattern.exec(line)?.[1];
|
||||
if (!match) { return completions; }
|
||||
|
||||
let segments = match.split('.');
|
||||
const prefix = segments.pop() ?? '';
|
||||
segments = segments.filter(segment => segment);
|
||||
const property = segments[segments.length - 1];
|
||||
const propertyCompletions = this.completions[property]?.completions != null ? this.completions[property]?.completions : [];
|
||||
for (let completion of propertyCompletions) {
|
||||
if (!prefix || firstCharsEqual(completion.name, prefix)) {
|
||||
completions.push(clone(completion));
|
||||
}
|
||||
}
|
||||
return completions;
|
||||
},
|
||||
|
||||
getPropertyClass(name) {
|
||||
return atom[name]?.constructor?.name;
|
||||
},
|
||||
|
||||
loadProperty(propertyName, className, classes, parent) {
|
||||
const classCompletions = classes[className];
|
||||
if (classCompletions == null) { return; }
|
||||
|
||||
this.completions[propertyName] = {completions: []};
|
||||
|
||||
for (let completion of classCompletions) {
|
||||
this.completions[propertyName].completions.push(completion);
|
||||
if (completion.type === 'property') {
|
||||
const propertyClass = this.getPropertyClass(completion.name);
|
||||
this.loadProperty(completion.name, propertyClass, classes);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const clone = function(obj) {
|
||||
const newObj = {};
|
||||
for (let k in obj) { const v = obj[k]; newObj[k] = v; }
|
||||
return newObj;
|
||||
};
|
||||
|
||||
const firstCharsEqual = (str1, str2) => str1[0].toLowerCase() === str2[0].toLowerCase();
|
@ -1,142 +0,0 @@
|
||||
_ = require 'underscore-plus'
|
||||
|
||||
CharacterPattern = ///
|
||||
[
|
||||
^\s
|
||||
]
|
||||
///
|
||||
|
||||
module.exports =
|
||||
activate: ->
|
||||
@commandDisposable = atom.commands.add 'atom-text-editor',
|
||||
'autoflow:reflow-selection': (event) =>
|
||||
@reflowSelection(event.currentTarget.getModel())
|
||||
|
||||
deactivate: ->
|
||||
@commandDisposable?.dispose()
|
||||
@commandDisposable = null
|
||||
|
||||
reflowSelection: (editor) ->
|
||||
range = editor.getSelectedBufferRange()
|
||||
range = editor.getCurrentParagraphBufferRange() if range.isEmpty()
|
||||
return unless range?
|
||||
|
||||
reflowOptions =
|
||||
wrapColumn: @getPreferredLineLength(editor)
|
||||
tabLength: @getTabLength(editor)
|
||||
reflowedText = @reflow(editor.getTextInRange(range), reflowOptions)
|
||||
editor.getBuffer().setTextInRange(range, reflowedText)
|
||||
|
||||
reflow: (text, {wrapColumn, tabLength}) ->
|
||||
paragraphs = []
|
||||
# Convert all \r\n and \r to \n. The text buffer will normalize them later
|
||||
text = text.replace(/\r\n?/g, '\n')
|
||||
|
||||
leadingVerticalSpace = text.match(/^\s*\n/)
|
||||
if leadingVerticalSpace
|
||||
text = text.substr(leadingVerticalSpace.length)
|
||||
else
|
||||
leadingVerticalSpace = ''
|
||||
|
||||
trailingVerticalSpace = text.match(/\n\s*$/)
|
||||
if trailingVerticalSpace
|
||||
text = text.substr(0, text.length - trailingVerticalSpace.length)
|
||||
else
|
||||
trailingVerticalSpace = ''
|
||||
|
||||
paragraphBlocks = text.split(/\n\s*\n/g)
|
||||
if tabLength
|
||||
tabLengthInSpaces = Array(tabLength + 1).join(' ')
|
||||
else
|
||||
tabLengthInSpaces = ''
|
||||
|
||||
for block in paragraphBlocks
|
||||
blockLines = block.split('\n')
|
||||
|
||||
# For LaTeX tags surrounding the text, we simply ignore them, and
|
||||
# reproduce them verbatim in the wrapped text.
|
||||
beginningLinesToIgnore = []
|
||||
endingLinesToIgnore = []
|
||||
latexTagRegex = /^\s*\\\w+(\[.*\])?\{\w+\}(\[.*\])?\s*$/g # e.g. \begin{verbatim}
|
||||
latexTagStartRegex = /^\s*\\\w+\s*\{\s*$/g # e.g. \item{
|
||||
latexTagEndRegex = /^\s*\}\s*$/g # e.g. }
|
||||
while blockLines.length > 0 and (
|
||||
blockLines[0].match(latexTagRegex) or
|
||||
blockLines[0].match(latexTagStartRegex))
|
||||
beginningLinesToIgnore.push(blockLines[0])
|
||||
blockLines.shift()
|
||||
while blockLines.length > 0 and (
|
||||
blockLines[blockLines.length - 1].match(latexTagRegex) or
|
||||
blockLines[blockLines.length - 1].match(latexTagEndRegex))
|
||||
endingLinesToIgnore.unshift(blockLines[blockLines.length - 1])
|
||||
blockLines.pop()
|
||||
|
||||
# The paragraph might be a LaTeX section with no text, only tags:
|
||||
# \documentclass{article}
|
||||
# In that case, we have nothing to reflow.
|
||||
# Push the tags verbatim and continue to the next paragraph.
|
||||
unless blockLines.length > 0
|
||||
paragraphs.push(block)
|
||||
continue
|
||||
|
||||
# TODO: this could be more language specific. Use the actual comment char.
|
||||
# Remember that `-` has to be the last character in the character class.
|
||||
linePrefix = blockLines[0].match(/^\s*(\/\/|\/\*|;;|#'|\|\|\||--|[#%*>-])?\s*/g)[0]
|
||||
linePrefixTabExpanded = linePrefix
|
||||
if tabLengthInSpaces
|
||||
linePrefixTabExpanded = linePrefix.replace(/\t/g, tabLengthInSpaces)
|
||||
|
||||
if linePrefix
|
||||
escapedLinePrefix = _.escapeRegExp(linePrefix)
|
||||
blockLines = blockLines.map (blockLine) ->
|
||||
blockLine.replace(///^#{escapedLinePrefix}///, '')
|
||||
|
||||
blockLines = blockLines.map (blockLine) ->
|
||||
blockLine.replace(/^\s+/, '')
|
||||
|
||||
lines = []
|
||||
currentLine = []
|
||||
currentLineLength = linePrefixTabExpanded.length
|
||||
|
||||
wrappedLinePrefix = linePrefix
|
||||
.replace(/^(\s*)\/\*/, '$1 ')
|
||||
.replace(/^(\s*)-(?!-)/, '$1 ')
|
||||
|
||||
firstLine = true
|
||||
for segment in @segmentText(blockLines.join(' '))
|
||||
if @wrapSegment(segment, currentLineLength, wrapColumn)
|
||||
|
||||
# Independent of line prefix don't mess with it on the first line
|
||||
if firstLine isnt true
|
||||
# Handle C comments
|
||||
if linePrefix.search(/^\s*\/\*/) isnt -1 or linePrefix.search(/^\s*-(?!-)/) isnt -1
|
||||
linePrefix = wrappedLinePrefix
|
||||
lines.push(linePrefix + currentLine.join(''))
|
||||
currentLine = []
|
||||
currentLineLength = linePrefixTabExpanded.length
|
||||
firstLine = false
|
||||
currentLine.push(segment)
|
||||
currentLineLength += segment.length
|
||||
lines.push(linePrefix + currentLine.join(''))
|
||||
|
||||
wrappedLines = beginningLinesToIgnore.concat(lines.concat(endingLinesToIgnore))
|
||||
paragraphs.push(wrappedLines.join('\n').replace(/\s+\n/g, '\n'))
|
||||
|
||||
return leadingVerticalSpace + paragraphs.join('\n\n') + trailingVerticalSpace
|
||||
|
||||
getTabLength: (editor) ->
|
||||
atom.config.get('editor.tabLength', scope: editor.getRootScopeDescriptor()) ? 2
|
||||
|
||||
getPreferredLineLength: (editor) ->
|
||||
atom.config.get('editor.preferredLineLength', scope: editor.getRootScopeDescriptor())
|
||||
|
||||
wrapSegment: (segment, currentLineLength, wrapColumn) ->
|
||||
CharacterPattern.test(segment) and
|
||||
(currentLineLength + segment.length > wrapColumn) and
|
||||
(currentLineLength > 0 or segment.length < wrapColumn)
|
||||
|
||||
segmentText: (text) ->
|
||||
segments = []
|
||||
re = /[\s]+|[^\s]+/g
|
||||
segments.push(match[0]) while match = re.exec(text)
|
||||
segments
|
165
packages/autoflow/lib/autoflow.js
Normal file
165
packages/autoflow/lib/autoflow.js
Normal file
@ -0,0 +1,165 @@
|
||||
|
||||
const _ = require('underscore-plus');
|
||||
|
||||
const CharacterPattern = new RegExp(/[^\s]/);
|
||||
|
||||
module.exports = {
|
||||
activate() {
|
||||
this.commandDisposable = atom.commands.add('atom-text-editor', {
|
||||
'autoflow:reflow-selection': event => {
|
||||
this.reflowSelection(event.currentTarget.getModel());
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
deactivate() {
|
||||
this.commandDisposable?.dispose();
|
||||
this.commandDisposable = null;
|
||||
},
|
||||
|
||||
reflowSelection(editor) {
|
||||
let range = editor.getSelectedBufferRange();
|
||||
if (range.isEmpty()) { range = editor.getCurrentParagraphBufferRange(); }
|
||||
if (range == null) { return; }
|
||||
|
||||
const reflowOptions = {
|
||||
wrapColumn: this.getPreferredLineLength(editor),
|
||||
tabLength: this.getTabLength(editor)
|
||||
};
|
||||
const reflowedText = this.reflow(editor.getTextInRange(range), reflowOptions);
|
||||
return editor.getBuffer().setTextInRange(range, reflowedText);
|
||||
},
|
||||
|
||||
reflow(text, {wrapColumn, tabLength}) {
|
||||
let tabLengthInSpaces;
|
||||
const paragraphs = [];
|
||||
// Convert all \r\n and \r to \n. The text buffer will normalize them later
|
||||
text = text.replace(/\r\n?/g, '\n');
|
||||
|
||||
let leadingVerticalSpace = text.match(/^\s*\n/);
|
||||
if (leadingVerticalSpace) {
|
||||
text = text.substr(leadingVerticalSpace.length);
|
||||
} else {
|
||||
leadingVerticalSpace = '';
|
||||
}
|
||||
|
||||
let trailingVerticalSpace = text.match(/\n\s*$/);
|
||||
if (trailingVerticalSpace) {
|
||||
text = text.substr(0, text.length - trailingVerticalSpace.length);
|
||||
} else {
|
||||
trailingVerticalSpace = '';
|
||||
}
|
||||
|
||||
const paragraphBlocks = text.split(/\n\s*\n/g);
|
||||
if (tabLength) {
|
||||
tabLengthInSpaces = Array(tabLength + 1).join(' ');
|
||||
} else {
|
||||
tabLengthInSpaces = '';
|
||||
}
|
||||
|
||||
for (let block of paragraphBlocks) {
|
||||
let blockLines = block.split('\n');
|
||||
|
||||
// For LaTeX tags surrounding the text, we simply ignore them, and
|
||||
// reproduce them verbatim in the wrapped text.
|
||||
const beginningLinesToIgnore = [];
|
||||
const endingLinesToIgnore = [];
|
||||
const latexTagRegex = /^\s*\\\w+(\[.*\])?\{\w+\}(\[.*\])?\s*$/g; // e.g. \begin{verbatim}
|
||||
const latexTagStartRegex = /^\s*\\\w+\s*\{\s*$/g; // e.g. \item{
|
||||
const latexTagEndRegex = /^\s*\}\s*$/g; // e.g. }
|
||||
while ((blockLines.length > 0) && (
|
||||
blockLines[0].match(latexTagRegex) ||
|
||||
blockLines[0].match(latexTagStartRegex))) {
|
||||
beginningLinesToIgnore.push(blockLines[0]);
|
||||
blockLines.shift();
|
||||
}
|
||||
while ((blockLines.length > 0) && (
|
||||
blockLines[blockLines.length - 1].match(latexTagRegex) ||
|
||||
blockLines[blockLines.length - 1].match(latexTagEndRegex))) {
|
||||
endingLinesToIgnore.unshift(blockLines[blockLines.length - 1]);
|
||||
blockLines.pop();
|
||||
}
|
||||
|
||||
// The paragraph might be a LaTeX section with no text, only tags:
|
||||
// \documentclass{article}
|
||||
// In that case, we have nothing to reflow.
|
||||
// Push the tags verbatim and continue to the next paragraph.
|
||||
if (!(blockLines.length > 0)) {
|
||||
paragraphs.push(block);
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: this could be more language specific. Use the actual comment char.
|
||||
// Remember that `-` has to be the last character in the character class.
|
||||
let linePrefix = blockLines[0].match(/^\s*(\/\/|\/\*|;;|#'|\|\|\||--|[#%*>-])?\s*/g)[0];
|
||||
let linePrefixTabExpanded = linePrefix;
|
||||
if (tabLengthInSpaces) {
|
||||
linePrefixTabExpanded = linePrefix.replace(/\t/g, tabLengthInSpaces);
|
||||
}
|
||||
|
||||
if (linePrefix) {
|
||||
var escapedLinePrefix = _.escapeRegExp(linePrefix);
|
||||
blockLines = blockLines.map(blockLine => blockLine.replace(new RegExp(`^${escapedLinePrefix}`), ''));
|
||||
}
|
||||
|
||||
blockLines = blockLines.map(blockLine => blockLine.replace(/^\s+/, ''));
|
||||
|
||||
const lines = [];
|
||||
let currentLine = [];
|
||||
let currentLineLength = linePrefixTabExpanded.length;
|
||||
|
||||
const wrappedLinePrefix = linePrefix
|
||||
.replace(/^(\s*)\/\*/, '$1 ')
|
||||
.replace(/^(\s*)-(?!-)/, '$1 ');
|
||||
|
||||
let firstLine = true;
|
||||
for (let segment of this.segmentText(blockLines.join(' '))) {
|
||||
if (this.wrapSegment(segment, currentLineLength, wrapColumn)) {
|
||||
|
||||
// Independent of line prefix don't mess with it on the first line
|
||||
if (firstLine !== true) {
|
||||
// Handle C comments
|
||||
if ((linePrefix.search(/^\s*\/\*/) !== -1) || (linePrefix.search(/^\s*-(?!-)/) !== -1)) {
|
||||
linePrefix = wrappedLinePrefix;
|
||||
}
|
||||
}
|
||||
lines.push(linePrefix + currentLine.join(''));
|
||||
currentLine = [];
|
||||
currentLineLength = linePrefixTabExpanded.length;
|
||||
firstLine = false;
|
||||
}
|
||||
currentLine.push(segment);
|
||||
currentLineLength += segment.length;
|
||||
}
|
||||
lines.push(linePrefix + currentLine.join(''));
|
||||
|
||||
const wrappedLines = beginningLinesToIgnore.concat(lines.concat(endingLinesToIgnore));
|
||||
paragraphs.push(wrappedLines.join('\n').replace(/\s+\n/g, '\n'));
|
||||
}
|
||||
|
||||
return leadingVerticalSpace + paragraphs.join('\n\n') + trailingVerticalSpace;
|
||||
},
|
||||
|
||||
getTabLength(editor) {
|
||||
return atom.config.get('editor.tabLength', { scope: editor.getRootScopeDescriptor() }) ?? 2;
|
||||
},
|
||||
|
||||
getPreferredLineLength(editor) {
|
||||
return atom.config.get('editor.preferredLineLength', {scope: editor.getRootScopeDescriptor()});
|
||||
},
|
||||
|
||||
wrapSegment(segment, currentLineLength, wrapColumn) {
|
||||
return CharacterPattern.test(segment) &&
|
||||
((currentLineLength + segment.length) > wrapColumn) &&
|
||||
((currentLineLength > 0) || (segment.length < wrapColumn));
|
||||
},
|
||||
|
||||
segmentText(text) {
|
||||
let match;
|
||||
const segments = [];
|
||||
const re = /[\s]+|[^\s]+/g;
|
||||
while ((match = re.exec(text))) { segments.push(match[0]); }
|
||||
return segments;
|
||||
}
|
||||
};
|
@ -1,68 +0,0 @@
|
||||
{CompositeDisposable, Disposable} = require 'atom'
|
||||
_ = require 'underscore-plus'
|
||||
Grim = require 'grim'
|
||||
|
||||
module.exports =
|
||||
class DeprecationCopStatusBarView
|
||||
lastLength: null
|
||||
toolTipDisposable: null
|
||||
|
||||
constructor: ->
|
||||
@subscriptions = new CompositeDisposable
|
||||
|
||||
@element = document.createElement('div')
|
||||
@element.classList.add('deprecation-cop-status', 'inline-block', 'text-warning')
|
||||
@element.setAttribute('tabindex', -1)
|
||||
|
||||
@icon = document.createElement('span')
|
||||
@icon.classList.add('icon', 'icon-alert')
|
||||
@element.appendChild(@icon)
|
||||
|
||||
@deprecationNumber = document.createElement('span')
|
||||
@deprecationNumber.classList.add('deprecation-number')
|
||||
@deprecationNumber.textContent = '0'
|
||||
@element.appendChild(@deprecationNumber)
|
||||
|
||||
clickHandler = ->
|
||||
workspaceElement = atom.views.getView(atom.workspace)
|
||||
atom.commands.dispatch workspaceElement, 'deprecation-cop:view'
|
||||
@element.addEventListener('click', clickHandler)
|
||||
@subscriptions.add(new Disposable(=> @element.removeEventListener('click', clickHandler)))
|
||||
|
||||
@update()
|
||||
|
||||
debouncedUpdateDeprecatedSelectorCount = _.debounce(@update, 1000)
|
||||
|
||||
@subscriptions.add Grim.on 'updated', @update
|
||||
# TODO: Remove conditional when the new StyleManager deprecation APIs reach stable.
|
||||
if atom.styles.onDidUpdateDeprecations?
|
||||
@subscriptions.add(atom.styles.onDidUpdateDeprecations(debouncedUpdateDeprecatedSelectorCount))
|
||||
|
||||
destroy: ->
|
||||
@subscriptions.dispose()
|
||||
@element.remove()
|
||||
|
||||
getDeprecatedCallCount: ->
|
||||
Grim.getDeprecations().map((d) -> d.getStackCount()).reduce(((a, b) -> a + b), 0)
|
||||
|
||||
getDeprecatedStyleSheetsCount: ->
|
||||
# TODO: Remove conditional when the new StyleManager deprecation APIs reach stable.
|
||||
if atom.styles.getDeprecations?
|
||||
Object.keys(atom.styles.getDeprecations()).length
|
||||
else
|
||||
0
|
||||
|
||||
update: =>
|
||||
length = @getDeprecatedCallCount() + @getDeprecatedStyleSheetsCount()
|
||||
|
||||
return if @lastLength is length
|
||||
|
||||
@lastLength = length
|
||||
@deprecationNumber.textContent = "#{_.pluralize(length, 'deprecation')}"
|
||||
@toolTipDisposable?.dispose()
|
||||
@toolTipDisposable = atom.tooltips.add @element, title: "#{_.pluralize(length, 'call')} to deprecated methods"
|
||||
|
||||
if length is 0
|
||||
@element.style.display = 'none'
|
||||
else
|
||||
@element.style.display = ''
|
104
packages/deprecation-cop/lib/deprecation-cop-status-bar-view.js
Normal file
104
packages/deprecation-cop/lib/deprecation-cop-status-bar-view.js
Normal file
@ -0,0 +1,104 @@
|
||||
|
||||
const { CompositeDisposable, Disposable } = require("atom");
|
||||
const _ = require("underscore-plus");
|
||||
const Grim = require("grim");
|
||||
|
||||
module.exports = class DeprecationCopStatusBarView {
|
||||
static lastLength = null;
|
||||
static toolTipDisposable = null;
|
||||
|
||||
constructor() {
|
||||
this.update = this.update.bind(this);
|
||||
this.subscriptions = new CompositeDisposable();
|
||||
|
||||
this.element = document.createElement("div");
|
||||
this.element.classList.add(
|
||||
"deprecation-cop-status",
|
||||
"inline-block",
|
||||
"text-warning"
|
||||
);
|
||||
this.element.setAttribute("tabindex", -1);
|
||||
|
||||
this.icon = document.createElement("span");
|
||||
this.icon.classList.add("icon", "icon-alert");
|
||||
this.element.appendChild(this.icon);
|
||||
|
||||
this.deprecationNumber = document.createElement("span");
|
||||
this.deprecationNumber.classList.add("deprecation-number");
|
||||
this.deprecationNumber.textContent = "0";
|
||||
this.element.appendChild(this.deprecationNumber);
|
||||
|
||||
const clickHandler = function () {
|
||||
const workspaceElement = atom.views.getView(atom.workspace);
|
||||
atom.commands.dispatch(workspaceElement, "deprecation-cop:view");
|
||||
};
|
||||
this.element.addEventListener("click", clickHandler);
|
||||
this.subscriptions.add(
|
||||
new Disposable(() =>
|
||||
this.element.removeEventListener("click", clickHandler)
|
||||
)
|
||||
);
|
||||
|
||||
this.update();
|
||||
|
||||
const debouncedUpdateDeprecatedSelectorCount = _.debounce(
|
||||
this.update,
|
||||
1000
|
||||
);
|
||||
|
||||
this.subscriptions.add(Grim.on("updated", this.update));
|
||||
// TODO: Remove conditional when the new StyleManager deprecation APIs reach stable.
|
||||
if (atom.styles.onDidUpdateDeprecations != null) {
|
||||
this.subscriptions.add(
|
||||
atom.styles.onDidUpdateDeprecations(
|
||||
debouncedUpdateDeprecatedSelectorCount
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.subscriptions.dispose();
|
||||
this.element.remove();
|
||||
}
|
||||
|
||||
getDeprecatedCallCount() {
|
||||
return Grim.getDeprecations()
|
||||
.map((d) => d.getStackCount())
|
||||
.reduce((a, b) => a + b, 0);
|
||||
}
|
||||
|
||||
getDeprecatedStyleSheetsCount() {
|
||||
// TODO: Remove conditional when the new StyleManager deprecation APIs reach stable.
|
||||
if (atom.styles.getDeprecations != null) {
|
||||
return Object.keys(atom.styles.getDeprecations()).length;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
update() {
|
||||
const length =
|
||||
this.getDeprecatedCallCount() + this.getDeprecatedStyleSheetsCount();
|
||||
|
||||
if (this.lastLength === length) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.lastLength = length;
|
||||
this.deprecationNumber.textContent = `${_.pluralize(
|
||||
length,
|
||||
"deprecation"
|
||||
)}`;
|
||||
this.toolTipDisposable?.dispose();
|
||||
this.toolTipDisposable = atom.tooltips.add(this.element, {
|
||||
title: `${_.pluralize(length, "call")} to deprecated methods`,
|
||||
});
|
||||
|
||||
if (length === 0) {
|
||||
return (this.element.style.display = "none");
|
||||
} else {
|
||||
return (this.element.style.display = "");
|
||||
}
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue
Block a user