mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-09-19 06:58:26 +03:00
7f38e3f641
Making code modular by introducing Selector class
172 lines
5.0 KiB
JavaScript
172 lines
5.0 KiB
JavaScript
'use babel';
|
|
|
|
import _ from 'underscore-plus';
|
|
import { CompositeDisposable, Disposable } from 'atom';
|
|
import { Selector } from './selector';
|
|
import StatusBarItem from './status-bar-item';
|
|
import helpers from './helpers';
|
|
|
|
const LineEndingRegExp = /\r\n|\n/g;
|
|
|
|
// the following regular expression is executed natively via the `substring` package,
|
|
// where `\A` corresponds to the beginning of the string.
|
|
// More info: https://github.com/atom/line-ending-selector/pull/56
|
|
// eslint-disable-next-line no-useless-escape
|
|
const LFRegExp = /(\A|[^\r])\n/g;
|
|
const CRLFRegExp = /\r\n/g;
|
|
|
|
let disposables = null;
|
|
|
|
export function activate() {
|
|
disposables = new CompositeDisposable();
|
|
let selectorDisposable;
|
|
let selector;
|
|
|
|
disposables.add(
|
|
atom.commands.add('atom-text-editor', {
|
|
'line-ending-selector:show': () => {
|
|
// Initiating Selector object - called only once when `line-ending-selector:show` is called
|
|
if (!selectorDisposable) {
|
|
// make a Selector object
|
|
selector = new Selector([
|
|
{ name: 'LF', value: '\n' },
|
|
{ name: 'CRLF', value: '\r\n' }
|
|
]);
|
|
// Add disposable for selector
|
|
selectorDisposable = new Disposable(() => selector.dispose());
|
|
disposables.add(selectorDisposable);
|
|
}
|
|
|
|
selector.show();
|
|
},
|
|
|
|
'line-ending-selector:convert-to-LF': event => {
|
|
const editorElement = event.target.closest('atom-text-editor');
|
|
setLineEnding(editorElement.getModel(), '\n');
|
|
},
|
|
|
|
'line-ending-selector:convert-to-CRLF': event => {
|
|
const editorElement = event.target.closest('atom-text-editor');
|
|
setLineEnding(editorElement.getModel(), '\r\n');
|
|
}
|
|
})
|
|
);
|
|
}
|
|
|
|
export function deactivate() {
|
|
disposables.dispose();
|
|
}
|
|
|
|
export function consumeStatusBar(statusBar) {
|
|
let statusBarItem = new StatusBarItem();
|
|
let currentBufferDisposable = null;
|
|
let tooltipDisposable = null;
|
|
|
|
const updateTile = _.debounce(buffer => {
|
|
getLineEndings(buffer).then(lineEndings => {
|
|
if (lineEndings.size === 0) {
|
|
let defaultLineEnding = getDefaultLineEnding();
|
|
buffer.setPreferredLineEnding(defaultLineEnding);
|
|
lineEndings = new Set().add(defaultLineEnding);
|
|
}
|
|
statusBarItem.setLineEndings(lineEndings);
|
|
});
|
|
}, 0);
|
|
|
|
disposables.add(
|
|
atom.workspace.observeActiveTextEditor(editor => {
|
|
if (currentBufferDisposable) currentBufferDisposable.dispose();
|
|
|
|
if (editor && editor.getBuffer) {
|
|
let buffer = editor.getBuffer();
|
|
updateTile(buffer);
|
|
currentBufferDisposable = buffer.onDidChange(({ oldText, newText }) => {
|
|
if (!statusBarItem.hasLineEnding('\n')) {
|
|
if (newText.indexOf('\n') >= 0) {
|
|
updateTile(buffer);
|
|
}
|
|
} else if (!statusBarItem.hasLineEnding('\r\n')) {
|
|
if (newText.indexOf('\r\n') >= 0) {
|
|
updateTile(buffer);
|
|
}
|
|
} else if (oldText.indexOf('\n')) {
|
|
updateTile(buffer);
|
|
}
|
|
});
|
|
} else {
|
|
statusBarItem.setLineEndings(new Set());
|
|
currentBufferDisposable = null;
|
|
}
|
|
|
|
if (tooltipDisposable) {
|
|
disposables.remove(tooltipDisposable);
|
|
tooltipDisposable.dispose();
|
|
}
|
|
tooltipDisposable = atom.tooltips.add(statusBarItem.element, {
|
|
title() {
|
|
return `File uses ${statusBarItem.description()} line endings`;
|
|
}
|
|
});
|
|
disposables.add(tooltipDisposable);
|
|
})
|
|
);
|
|
|
|
disposables.add(
|
|
new Disposable(() => {
|
|
if (currentBufferDisposable) currentBufferDisposable.dispose();
|
|
})
|
|
);
|
|
|
|
statusBarItem.onClick(() => {
|
|
const editor = atom.workspace.getActiveTextEditor();
|
|
atom.commands.dispatch(
|
|
atom.views.getView(editor),
|
|
'line-ending-selector:show'
|
|
);
|
|
});
|
|
|
|
let tile = statusBar.addRightTile({ item: statusBarItem, priority: 200 });
|
|
disposables.add(new Disposable(() => tile.destroy()));
|
|
}
|
|
|
|
function getDefaultLineEnding() {
|
|
switch (atom.config.get('line-ending-selector.defaultLineEnding')) {
|
|
case 'LF':
|
|
return '\n';
|
|
case 'CRLF':
|
|
return '\r\n';
|
|
case 'OS Default':
|
|
default:
|
|
return helpers.getProcessPlatform() === 'win32' ? '\r\n' : '\n';
|
|
}
|
|
}
|
|
|
|
function getLineEndings(buffer) {
|
|
if (typeof buffer.find === 'function') {
|
|
return Promise.all([buffer.find(LFRegExp), buffer.find(CRLFRegExp)]).then(
|
|
([hasLF, hasCRLF]) => {
|
|
const result = new Set();
|
|
if (hasLF) result.add('\n');
|
|
if (hasCRLF) result.add('\r\n');
|
|
return result;
|
|
}
|
|
);
|
|
} else {
|
|
return new Promise(resolve => {
|
|
const result = new Set();
|
|
for (let i = 0; i < buffer.getLineCount() - 1; i++) {
|
|
result.add(buffer.lineEndingForRow(i));
|
|
}
|
|
resolve(result);
|
|
});
|
|
}
|
|
}
|
|
|
|
export function setLineEnding(item, lineEnding) {
|
|
if (item && item.getBuffer) {
|
|
let buffer = item.getBuffer();
|
|
buffer.setPreferredLineEnding(lineEnding);
|
|
buffer.setText(buffer.getText().replace(LineEndingRegExp, lineEnding));
|
|
}
|
|
}
|