mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-08-17 23:20:21 +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