mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-09-11 19:17:09 +03:00
Merge pull request #478 from pulsar-edit/wrap-guide-decaf
Add decaf changes to `master`
This commit is contained in:
commit
fe89387509
@ -1,26 +0,0 @@
|
|||||||
{CompositeDisposable} = require 'atom'
|
|
||||||
WrapGuideElement = require './wrap-guide-element'
|
|
||||||
|
|
||||||
module.exports =
|
|
||||||
activate: ->
|
|
||||||
@subscriptions = new CompositeDisposable()
|
|
||||||
@wrapGuides = new Map()
|
|
||||||
|
|
||||||
@subscriptions.add atom.workspace.observeTextEditors (editor) =>
|
|
||||||
return if @wrapGuides.has(editor)
|
|
||||||
|
|
||||||
editorElement = atom.views.getView(editor)
|
|
||||||
wrapGuideElement = new WrapGuideElement(editor, editorElement)
|
|
||||||
|
|
||||||
@wrapGuides.set(editor, wrapGuideElement)
|
|
||||||
@subscriptions.add editor.onDidDestroy =>
|
|
||||||
@wrapGuides.get(editor).destroy()
|
|
||||||
@wrapGuides.delete(editor)
|
|
||||||
|
|
||||||
deactivate: ->
|
|
||||||
@subscriptions.dispose()
|
|
||||||
@wrapGuides.forEach (wrapGuide, editor) -> wrapGuide.destroy()
|
|
||||||
@wrapGuides.clear()
|
|
||||||
|
|
||||||
uniqueAscending: (list) ->
|
|
||||||
(list.filter((item, index) -> list.indexOf(item) is index)).sort((a, b) -> a - b)
|
|
34
packages/wrap-guide/lib/main.js
Normal file
34
packages/wrap-guide/lib/main.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
const {CompositeDisposable} = require('atom');
|
||||||
|
const WrapGuideElement = require('./wrap-guide-element');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
activate() {
|
||||||
|
this.subscriptions = new CompositeDisposable();
|
||||||
|
this.wrapGuides = new Map();
|
||||||
|
|
||||||
|
this.subscriptions.add(atom.workspace.observeTextEditors(editor => {
|
||||||
|
if (this.wrapGuides.has(editor)) { return; }
|
||||||
|
|
||||||
|
const editorElement = atom.views.getView(editor);
|
||||||
|
const wrapGuideElement = new WrapGuideElement(editor, editorElement);
|
||||||
|
|
||||||
|
this.wrapGuides.set(editor, wrapGuideElement);
|
||||||
|
this.subscriptions.add(editor.onDidDestroy(() => {
|
||||||
|
this.wrapGuides.get(editor).destroy();
|
||||||
|
this.wrapGuides.delete(editor);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
deactivate() {
|
||||||
|
this.subscriptions.dispose();
|
||||||
|
this.wrapGuides.forEach((wrapGuide, editor) => wrapGuide.destroy());
|
||||||
|
return this.wrapGuides.clear();
|
||||||
|
},
|
||||||
|
|
||||||
|
uniqueAscending(list) {
|
||||||
|
return (list.filter((item, index) => list.indexOf(item) === index)).sort((a, b) => a - b);
|
||||||
|
}
|
||||||
|
};
|
@ -1,137 +0,0 @@
|
|||||||
{CompositeDisposable} = require 'atom'
|
|
||||||
|
|
||||||
module.exports =
|
|
||||||
class WrapGuideElement
|
|
||||||
constructor: (@editor, @editorElement) ->
|
|
||||||
@subscriptions = new CompositeDisposable()
|
|
||||||
@configSubscriptions = new CompositeDisposable()
|
|
||||||
@element = document.createElement('div')
|
|
||||||
@element.setAttribute('is', 'wrap-guide')
|
|
||||||
@element.classList.add('wrap-guide-container')
|
|
||||||
@attachToLines()
|
|
||||||
@handleEvents()
|
|
||||||
@updateGuide()
|
|
||||||
|
|
||||||
@element.updateGuide = @updateGuide.bind(this)
|
|
||||||
@element.getDefaultColumn = @getDefaultColumn.bind(this)
|
|
||||||
|
|
||||||
attachToLines: ->
|
|
||||||
scrollView = @editorElement.querySelector('.scroll-view')
|
|
||||||
scrollView?.appendChild(@element)
|
|
||||||
|
|
||||||
handleEvents: ->
|
|
||||||
updateGuideCallback = => @updateGuide()
|
|
||||||
|
|
||||||
@handleConfigEvents()
|
|
||||||
|
|
||||||
@subscriptions.add atom.config.onDidChange 'editor.fontSize', =>
|
|
||||||
# Wait for editor to finish updating before updating wrap guide
|
|
||||||
# TODO: Use async/await once this file is converted to JS
|
|
||||||
@editorElement.getComponent().getNextUpdatePromise().then -> updateGuideCallback()
|
|
||||||
|
|
||||||
@subscriptions.add @editorElement.onDidChangeScrollLeft(updateGuideCallback)
|
|
||||||
@subscriptions.add @editor.onDidChangePath(updateGuideCallback)
|
|
||||||
@subscriptions.add @editor.onDidChangeGrammar =>
|
|
||||||
@configSubscriptions.dispose()
|
|
||||||
@handleConfigEvents()
|
|
||||||
updateGuideCallback()
|
|
||||||
|
|
||||||
@subscriptions.add @editor.onDidDestroy =>
|
|
||||||
@subscriptions.dispose()
|
|
||||||
@configSubscriptions.dispose()
|
|
||||||
|
|
||||||
@subscriptions.add @editorElement.onDidAttach =>
|
|
||||||
@attachToLines()
|
|
||||||
updateGuideCallback()
|
|
||||||
|
|
||||||
handleConfigEvents: ->
|
|
||||||
{uniqueAscending} = require './main'
|
|
||||||
|
|
||||||
updatePreferredLineLengthCallback = (args) =>
|
|
||||||
# ensure that the right-most wrap guide is the preferredLineLength
|
|
||||||
columns = atom.config.get('wrap-guide.columns', scope: @editor.getRootScopeDescriptor())
|
|
||||||
if columns.length > 0
|
|
||||||
columns[columns.length - 1] = args.newValue
|
|
||||||
columns = uniqueAscending(i for i in columns when i <= args.newValue)
|
|
||||||
atom.config.set 'wrap-guide.columns', columns,
|
|
||||||
scopeSelector: ".#{@editor.getGrammar().scopeName}"
|
|
||||||
@updateGuide()
|
|
||||||
@configSubscriptions.add atom.config.onDidChange(
|
|
||||||
'editor.preferredLineLength',
|
|
||||||
scope: @editor.getRootScopeDescriptor(),
|
|
||||||
updatePreferredLineLengthCallback
|
|
||||||
)
|
|
||||||
|
|
||||||
updateGuideCallback = => @updateGuide()
|
|
||||||
@configSubscriptions.add atom.config.onDidChange(
|
|
||||||
'wrap-guide.enabled',
|
|
||||||
scope: @editor.getRootScopeDescriptor(),
|
|
||||||
updateGuideCallback
|
|
||||||
)
|
|
||||||
|
|
||||||
updateGuidesCallback = (args) =>
|
|
||||||
# ensure that multiple guides stay sorted in ascending order
|
|
||||||
columns = uniqueAscending(args.newValue)
|
|
||||||
if columns?.length
|
|
||||||
atom.config.set('wrap-guide.columns', columns)
|
|
||||||
atom.config.set 'editor.preferredLineLength', columns[columns.length - 1],
|
|
||||||
scopeSelector: ".#{@editor.getGrammar().scopeName}"
|
|
||||||
@updateGuide()
|
|
||||||
@configSubscriptions.add atom.config.onDidChange(
|
|
||||||
'wrap-guide.columns',
|
|
||||||
scope: @editor.getRootScopeDescriptor(),
|
|
||||||
updateGuidesCallback
|
|
||||||
)
|
|
||||||
|
|
||||||
getDefaultColumn: ->
|
|
||||||
atom.config.get('editor.preferredLineLength', scope: @editor.getRootScopeDescriptor())
|
|
||||||
|
|
||||||
getGuidesColumns: (path, scopeName) ->
|
|
||||||
columns = atom.config.get('wrap-guide.columns', scope: @editor.getRootScopeDescriptor()) ? []
|
|
||||||
return columns if columns.length > 0
|
|
||||||
return [@getDefaultColumn()]
|
|
||||||
|
|
||||||
isEnabled: ->
|
|
||||||
atom.config.get('wrap-guide.enabled', scope: @editor.getRootScopeDescriptor()) ? true
|
|
||||||
|
|
||||||
hide: ->
|
|
||||||
@element.style.display = 'none'
|
|
||||||
|
|
||||||
show: ->
|
|
||||||
@element.style.display = 'block'
|
|
||||||
|
|
||||||
updateGuide: ->
|
|
||||||
if @isEnabled()
|
|
||||||
@updateGuides()
|
|
||||||
else
|
|
||||||
@hide()
|
|
||||||
|
|
||||||
updateGuides: ->
|
|
||||||
@removeGuides()
|
|
||||||
@appendGuides()
|
|
||||||
if @element.children.length
|
|
||||||
@show()
|
|
||||||
else
|
|
||||||
@hide()
|
|
||||||
|
|
||||||
destroy: ->
|
|
||||||
@element.remove()
|
|
||||||
@subscriptions.dispose()
|
|
||||||
@configSubscriptions.dispose()
|
|
||||||
|
|
||||||
removeGuides: ->
|
|
||||||
while @element.firstChild
|
|
||||||
@element.removeChild(@element.firstChild)
|
|
||||||
|
|
||||||
appendGuides: ->
|
|
||||||
columns = @getGuidesColumns(@editor.getPath(), @editor.getGrammar().scopeName)
|
|
||||||
for column in columns
|
|
||||||
@appendGuide(column) unless column < 0
|
|
||||||
|
|
||||||
appendGuide: (column) ->
|
|
||||||
columnWidth = @editorElement.getDefaultCharacterWidth() * column
|
|
||||||
columnWidth -= @editorElement.getScrollLeft()
|
|
||||||
guide = document.createElement('div')
|
|
||||||
guide.classList.add('wrap-guide')
|
|
||||||
guide.style.left = "#{Math.round(columnWidth)}px"
|
|
||||||
@element.appendChild(guide)
|
|
187
packages/wrap-guide/lib/wrap-guide-element.js
Normal file
187
packages/wrap-guide/lib/wrap-guide-element.js
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
const {CompositeDisposable} = require('atom');
|
||||||
|
|
||||||
|
module.exports = class WrapGuideElement {
|
||||||
|
constructor(editor, editorElement) {
|
||||||
|
this.editor = editor;
|
||||||
|
this.editorElement = editorElement;
|
||||||
|
this.subscriptions = new CompositeDisposable();
|
||||||
|
this.configSubscriptions = new CompositeDisposable();
|
||||||
|
this.element = document.createElement('div');
|
||||||
|
this.element.setAttribute('is', 'wrap-guide');
|
||||||
|
this.element.classList.add('wrap-guide-container');
|
||||||
|
this.attachToLines();
|
||||||
|
this.handleEvents();
|
||||||
|
this.updateGuide();
|
||||||
|
|
||||||
|
this.element.updateGuide = this.updateGuide.bind(this);
|
||||||
|
this.element.getDefaultColumn = this.getDefaultColumn.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
attachToLines() {
|
||||||
|
const scrollView = this.editorElement.querySelector('.scroll-view');
|
||||||
|
return (scrollView != null ? scrollView.appendChild(this.element) : undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleEvents() {
|
||||||
|
const updateGuideCallback = () => this.updateGuide();
|
||||||
|
|
||||||
|
this.handleConfigEvents();
|
||||||
|
|
||||||
|
this.subscriptions.add(atom.config.onDidChange('editor.fontSize', () => {
|
||||||
|
// Wait for editor to finish updating before updating wrap guide
|
||||||
|
// TODO: Use async/await once this file is converted to JS
|
||||||
|
this.editorElement.getComponent().getNextUpdatePromise().then(() => updateGuideCallback());
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
this.subscriptions.add(this.editorElement.onDidChangeScrollLeft(updateGuideCallback));
|
||||||
|
this.subscriptions.add(this.editor.onDidChangePath(updateGuideCallback));
|
||||||
|
this.subscriptions.add(this.editor.onDidChangeGrammar(() => {
|
||||||
|
this.configSubscriptions.dispose();
|
||||||
|
this.handleConfigEvents();
|
||||||
|
updateGuideCallback();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
this.subscriptions.add(this.editor.onDidDestroy(() => {
|
||||||
|
this.subscriptions.dispose();
|
||||||
|
this.configSubscriptions.dispose();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
this.subscriptions.add(this.editorElement.onDidAttach(() => {
|
||||||
|
this.attachToLines();
|
||||||
|
updateGuideCallback();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleConfigEvents() {
|
||||||
|
const {uniqueAscending} = require('./main');
|
||||||
|
|
||||||
|
const updatePreferredLineLengthCallback = args => {
|
||||||
|
// ensure that the right-most wrap guide is the preferredLineLength
|
||||||
|
let columns = atom.config.get('wrap-guide.columns', {scope: this.editor.getRootScopeDescriptor()});
|
||||||
|
if (columns.length > 0) {
|
||||||
|
columns[columns.length - 1] = args.newValue;
|
||||||
|
columns = uniqueAscending(Array.from(columns).filter((i) => i <= args.newValue));
|
||||||
|
atom.config.set('wrap-guide.columns', columns,
|
||||||
|
{scopeSelector: `.${this.editor.getGrammar().scopeName}`});
|
||||||
|
}
|
||||||
|
return this.updateGuide();
|
||||||
|
};
|
||||||
|
this.configSubscriptions.add(atom.config.onDidChange(
|
||||||
|
'editor.preferredLineLength',
|
||||||
|
{scope: this.editor.getRootScopeDescriptor()},
|
||||||
|
updatePreferredLineLengthCallback
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const updateGuideCallback = () => this.updateGuide();
|
||||||
|
this.configSubscriptions.add(atom.config.onDidChange(
|
||||||
|
'wrap-guide.enabled',
|
||||||
|
{scope: this.editor.getRootScopeDescriptor()},
|
||||||
|
updateGuideCallback
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const updateGuidesCallback = args => {
|
||||||
|
// ensure that multiple guides stay sorted in ascending order
|
||||||
|
const columns = uniqueAscending(args.newValue);
|
||||||
|
if (columns != null ? columns.length : undefined) {
|
||||||
|
atom.config.set('wrap-guide.columns', columns);
|
||||||
|
atom.config.set('editor.preferredLineLength', columns[columns.length - 1],
|
||||||
|
{scopeSelector: `.${this.editor.getGrammar().scopeName}`});
|
||||||
|
return this.updateGuide();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return this.configSubscriptions.add(atom.config.onDidChange(
|
||||||
|
'wrap-guide.columns',
|
||||||
|
{scope: this.editor.getRootScopeDescriptor()},
|
||||||
|
updateGuidesCallback
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getDefaultColumn() {
|
||||||
|
return atom.config.get('editor.preferredLineLength', {scope: this.editor.getRootScopeDescriptor()});
|
||||||
|
}
|
||||||
|
|
||||||
|
getGuidesColumns(path, scopeName) {
|
||||||
|
let left;
|
||||||
|
const columns = (left = atom.config.get('wrap-guide.columns', {scope: this.editor.getRootScopeDescriptor()})) != null ? left : [];
|
||||||
|
if (columns.length > 0) { return columns; }
|
||||||
|
return [this.getDefaultColumn()];
|
||||||
|
}
|
||||||
|
|
||||||
|
isEnabled() {
|
||||||
|
let left;
|
||||||
|
return (left = atom.config.get('wrap-guide.enabled', {scope: this.editor.getRootScopeDescriptor()})) != null ? left : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
hide() {
|
||||||
|
return this.element.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
show() {
|
||||||
|
return this.element.style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
updateGuide() {
|
||||||
|
if (this.isEnabled()) {
|
||||||
|
return this.updateGuides();
|
||||||
|
} else {
|
||||||
|
return this.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateGuides() {
|
||||||
|
this.removeGuides();
|
||||||
|
this.appendGuides();
|
||||||
|
if (this.element.children.length) {
|
||||||
|
return this.show();
|
||||||
|
} else {
|
||||||
|
return this.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy() {
|
||||||
|
this.element.remove();
|
||||||
|
this.subscriptions.dispose();
|
||||||
|
return this.configSubscriptions.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
removeGuides() {
|
||||||
|
return (() => {
|
||||||
|
const result = [];
|
||||||
|
while (this.element.firstChild) {
|
||||||
|
result.push(this.element.removeChild(this.element.firstChild));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
appendGuides() {
|
||||||
|
const columns = this.getGuidesColumns(this.editor.getPath(), this.editor.getGrammar().scopeName);
|
||||||
|
return (() => {
|
||||||
|
const result = [];
|
||||||
|
for (let column of columns) {
|
||||||
|
if (!(column < 0)) {
|
||||||
|
result.push(this.appendGuide(column));
|
||||||
|
} else {
|
||||||
|
result.push(undefined);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
appendGuide(column) {
|
||||||
|
let columnWidth = this.editorElement.getDefaultCharacterWidth() * column;
|
||||||
|
columnWidth -= this.editorElement.getScrollLeft();
|
||||||
|
const guide = document.createElement('div');
|
||||||
|
guide.classList.add('wrap-guide');
|
||||||
|
guide.style.left = `${Math.round(columnWidth)}px`;
|
||||||
|
return this.element.appendChild(guide);
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user