mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-09-11 19:17:09 +03:00
Bundle wrap-guide
This commit is contained in:
parent
d9f2bbdfa7
commit
640e0dcf48
@ -170,7 +170,7 @@
|
||||
"welcome": "file:packages/welcome",
|
||||
"whitespace": "https://codeload.github.com/atom/whitespace/legacy.tar.gz/refs/tags/v0.37.8",
|
||||
"winreg": "^1.2.1",
|
||||
"wrap-guide": "https://codeload.github.com/atom/wrap-guide/legacy.tar.gz/refs/tags/v0.41.0",
|
||||
"wrap-guide": "file:./packages/wrap-guide",
|
||||
"yargs": "17.6.2"
|
||||
},
|
||||
"packageDependencies": {
|
||||
@ -231,7 +231,7 @@
|
||||
"update-package-dependencies": "file:./packages/update-package-dependencies",
|
||||
"welcome": "file:./packages/welcome",
|
||||
"whitespace": "0.37.8",
|
||||
"wrap-guide": "0.41.0",
|
||||
"wrap-guide": "file:./packages/wrap-guide",
|
||||
"language-c": "file:./packages/language-c",
|
||||
"language-clojure": "file:./packages/language-clojure",
|
||||
"language-coffee-script": "file:./packages/language-coffee-script",
|
||||
|
1
packages/wrap-guide/.gitignore
vendored
Normal file
1
packages/wrap-guide/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
node_modules
|
35
packages/wrap-guide/README.md
Normal file
35
packages/wrap-guide/README.md
Normal file
@ -0,0 +1,35 @@
|
||||
# Wrap Guide package
|
||||
|
||||
The `wrap-guide` package places a vertical line in each editor at a certain column to guide your formatting, so lines do not exceed a certain width.
|
||||
|
||||
By default, the wrap-guide is placed at the value of `editor.preferredLineLength` config setting. The 80th column is used as the fallback if the config value is unset.
|
||||
|
||||
![](https://f.cloud.github.com/assets/671378/2241976/dbf6a8f6-9ced-11e3-8fef-d8a226301530.png)
|
||||
|
||||
## Configuration
|
||||
|
||||
You can customize where the column is placed for different file types by opening the Settings View and configuring the "Preferred Line Length" value. If you do not want the guide to show for a particular language, that can be set using scoped configuration. For example, to turn off the guide for GitHub-Flavored Markdown, you can add the following to your `config.cson`:
|
||||
|
||||
```coffeescript
|
||||
'.source.gfm':
|
||||
'wrap-guide':
|
||||
'enabled': false
|
||||
```
|
||||
|
||||
It is possible to configure the color and/or width of the line by adding the following CSS/LESS to your `styles.less`:
|
||||
|
||||
```css
|
||||
atom-text-editor .wrap-guide {
|
||||
width: 10px;
|
||||
background-color: red;
|
||||
}
|
||||
```
|
||||
|
||||
Multiple guide lines are also supported. For example, add the following to your `config.cson` to create four columns at the indicated positions:
|
||||
|
||||
```coffeescript
|
||||
'wrap-guide':
|
||||
'columns': [72, 80, 100, 120]
|
||||
```
|
||||
|
||||
> Note: When using multiple guide lines, the right-most guide line functions as your `editor.preferredLineLength` setting.
|
26
packages/wrap-guide/lib/main.coffee
Normal file
26
packages/wrap-guide/lib/main.coffee
Normal file
@ -0,0 +1,26 @@
|
||||
{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)
|
137
packages/wrap-guide/lib/wrap-guide-element.coffee
Normal file
137
packages/wrap-guide/lib/wrap-guide-element.coffee
Normal file
@ -0,0 +1,137 @@
|
||||
{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)
|
16
packages/wrap-guide/package-lock.json
generated
Normal file
16
packages/wrap-guide/package-lock.json
generated
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "wrap-guide",
|
||||
"version": "0.41.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "wrap-guide",
|
||||
"version": "0.41.0",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"atom": "*"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
25
packages/wrap-guide/package.json
Normal file
25
packages/wrap-guide/package.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "wrap-guide",
|
||||
"version": "0.41.0",
|
||||
"main": "./lib/main",
|
||||
"description": "Displays a vertical line at the 80th character in the editor.\nThis packages uses the config value of `editor.preferredLineLength` when set.",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/pulsar-edit/wrap-guide",
|
||||
"engines": {
|
||||
"atom": "*"
|
||||
},
|
||||
"configSchema": {
|
||||
"columns": {
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer"
|
||||
},
|
||||
"description": "Display guides at each of the listed character widths. Leave blank for one guide at your `editor.preferredLineLength`."
|
||||
},
|
||||
"enabled": {
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
}
|
103
packages/wrap-guide/spec/async-spec-helpers.js
Normal file
103
packages/wrap-guide/spec/async-spec-helpers.js
Normal file
@ -0,0 +1,103 @@
|
||||
/** @babel */
|
||||
|
||||
export function beforeEach (fn) {
|
||||
global.beforeEach(function () {
|
||||
const result = fn()
|
||||
if (result instanceof Promise) {
|
||||
waitsForPromise(() => result)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function afterEach (fn) {
|
||||
global.afterEach(function () {
|
||||
const result = fn()
|
||||
if (result instanceof Promise) {
|
||||
waitsForPromise(() => result)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
['it', 'fit', 'ffit', 'fffit'].forEach(function (name) {
|
||||
module.exports[name] = function (description, fn) {
|
||||
if (fn === undefined) {
|
||||
global[name](description)
|
||||
return
|
||||
}
|
||||
|
||||
global[name](description, function () {
|
||||
const result = fn()
|
||||
if (result instanceof Promise) {
|
||||
waitsForPromise(() => result)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
export async function conditionPromise (condition, description = 'anonymous condition') {
|
||||
const startTime = Date.now()
|
||||
|
||||
while (true) {
|
||||
await timeoutPromise(100)
|
||||
|
||||
if (await condition()) {
|
||||
return
|
||||
}
|
||||
|
||||
if (Date.now() - startTime > 5000) {
|
||||
throw new Error('Timed out waiting on ' + description)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function timeoutPromise (timeout) {
|
||||
return new Promise(function (resolve) {
|
||||
global.setTimeout(resolve, timeout)
|
||||
})
|
||||
}
|
||||
|
||||
function waitsForPromise (fn) {
|
||||
const promise = fn()
|
||||
global.waitsFor('spec promise to resolve', function (done) {
|
||||
promise.then(done, function (error) {
|
||||
jasmine.getEnv().currentSpec.fail(error)
|
||||
done()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export function emitterEventPromise (emitter, event, timeout = 15000) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const timeoutHandle = setTimeout(() => {
|
||||
reject(new Error(`Timed out waiting for '${event}' event`))
|
||||
}, timeout)
|
||||
emitter.once(event, () => {
|
||||
clearTimeout(timeoutHandle)
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export function promisify (original) {
|
||||
return function (...args) {
|
||||
return new Promise((resolve, reject) => {
|
||||
args.push((err, ...results) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
resolve(...results)
|
||||
}
|
||||
})
|
||||
|
||||
return original(...args)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function promisifySome (obj, fnNames) {
|
||||
const result = {}
|
||||
for (const fnName of fnNames) {
|
||||
result[fnName] = promisify(obj[fnName])
|
||||
}
|
||||
return result
|
||||
}
|
20
packages/wrap-guide/spec/helpers.js
Normal file
20
packages/wrap-guide/spec/helpers.js
Normal file
@ -0,0 +1,20 @@
|
||||
const helpers = {
|
||||
getWrapGuides () {
|
||||
wrapGuides = []
|
||||
for (const editor of atom.workspace.getTextEditors()) {
|
||||
const guide = editor.getElement().querySelector('.wrap-guide')
|
||||
if (guide) wrapGuides.push(guide)
|
||||
}
|
||||
return wrapGuides
|
||||
},
|
||||
|
||||
getLeftPosition (element) {
|
||||
return parseInt(element.style.left)
|
||||
},
|
||||
|
||||
getLeftPositions (elements) {
|
||||
return Array.prototype.map.call(elements, element => helpers.getLeftPosition(element))
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = helpers
|
275
packages/wrap-guide/spec/wrap-guide-element-spec.coffee
Normal file
275
packages/wrap-guide/spec/wrap-guide-element-spec.coffee
Normal file
@ -0,0 +1,275 @@
|
||||
{getLeftPosition, getLeftPositions} = require './helpers'
|
||||
{uniqueAscending} = require '../lib/main'
|
||||
|
||||
describe "WrapGuideElement", ->
|
||||
[editor, editorElement, wrapGuide, workspaceElement] = []
|
||||
|
||||
beforeEach ->
|
||||
workspaceElement = atom.views.getView(atom.workspace)
|
||||
workspaceElement.style.height = "200px"
|
||||
workspaceElement.style.width = "1500px"
|
||||
|
||||
jasmine.attachToDOM(workspaceElement)
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('wrap-guide')
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-javascript')
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-coffee-script')
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.js')
|
||||
|
||||
runs ->
|
||||
editor = atom.workspace.getActiveTextEditor()
|
||||
editorElement = editor.getElement()
|
||||
wrapGuide = editorElement.querySelector(".wrap-guide-container")
|
||||
|
||||
describe ".activate", ->
|
||||
getWrapGuides = ->
|
||||
wrapGuides = []
|
||||
atom.workspace.getTextEditors().forEach (editor) ->
|
||||
guides = editor.getElement().querySelectorAll(".wrap-guide")
|
||||
wrapGuides.push(guides) if guides
|
||||
wrapGuides
|
||||
|
||||
it "appends a wrap guide to all existing and new editors", ->
|
||||
expect(atom.workspace.getTextEditors().length).toBe 1
|
||||
|
||||
expect(getWrapGuides().length).toBe 1
|
||||
expect(getLeftPosition(getWrapGuides()[0][0])).toBeGreaterThan(0)
|
||||
|
||||
atom.workspace.getActivePane().splitRight(copyActiveItem: true)
|
||||
expect(atom.workspace.getTextEditors().length).toBe 2
|
||||
expect(getWrapGuides().length).toBe 2
|
||||
expect(getLeftPosition(getWrapGuides()[0][0])).toBeGreaterThan(0)
|
||||
expect(getLeftPosition(getWrapGuides()[1][0])).toBeGreaterThan(0)
|
||||
|
||||
it "positions the guide at the configured column", ->
|
||||
width = editor.getDefaultCharWidth() * wrapGuide.getDefaultColumn()
|
||||
expect(width).toBeGreaterThan(0)
|
||||
expect(Math.abs(getLeftPosition(wrapGuide.firstChild) - width)).toBeLessThan 1
|
||||
expect(wrapGuide).toBeVisible()
|
||||
|
||||
it "appends multiple wrap guides to all existing and new editors", ->
|
||||
columns = [10, 20, 30]
|
||||
atom.config.set("wrap-guide.columns", columns)
|
||||
|
||||
waitsForPromise ->
|
||||
editorElement.getComponent().getNextUpdatePromise()
|
||||
|
||||
runs ->
|
||||
expect(atom.workspace.getTextEditors().length).toBe 1
|
||||
expect(getWrapGuides().length).toBe 1
|
||||
positions = getLeftPositions(getWrapGuides()[0])
|
||||
expect(positions.length).toBe(columns.length)
|
||||
expect(positions[0]).toBeGreaterThan(0)
|
||||
expect(positions[1]).toBeGreaterThan(positions[0])
|
||||
expect(positions[2]).toBeGreaterThan(positions[1])
|
||||
|
||||
atom.workspace.getActivePane().splitRight(copyActiveItem: true)
|
||||
expect(atom.workspace.getTextEditors().length).toBe 2
|
||||
expect(getWrapGuides().length).toBe 2
|
||||
pane1_positions = getLeftPositions(getWrapGuides()[0])
|
||||
expect(pane1_positions.length).toBe(columns.length)
|
||||
expect(pane1_positions[0]).toBeGreaterThan(0)
|
||||
expect(pane1_positions[1]).toBeGreaterThan(pane1_positions[0])
|
||||
expect(pane1_positions[2]).toBeGreaterThan(pane1_positions[1])
|
||||
pane2_positions = getLeftPositions(getWrapGuides()[1])
|
||||
expect(pane2_positions.length).toBe(pane1_positions.length)
|
||||
expect(pane2_positions[0]).toBe(pane1_positions[0])
|
||||
expect(pane2_positions[1]).toBe(pane1_positions[1])
|
||||
expect(pane2_positions[2]).toBe(pane1_positions[2])
|
||||
|
||||
it "positions multiple guides at the configured columns", ->
|
||||
columnCount = 5
|
||||
columns = (c * 10 for c in [1..columnCount])
|
||||
atom.config.set("wrap-guide.columns", columns)
|
||||
waitsForPromise ->
|
||||
editorElement.getComponent().getNextUpdatePromise()
|
||||
|
||||
runs ->
|
||||
positions = getLeftPositions(getWrapGuides()[0])
|
||||
expect(positions.length).toBe(columnCount)
|
||||
expect(wrapGuide.children.length).toBe(columnCount)
|
||||
|
||||
for i in columnCount - 1
|
||||
width = editor.getDefaultCharWidth() * columns[i]
|
||||
expect(width).toBeGreaterThan(0)
|
||||
expect(Math.abs(getLeftPosition(wrapGuide.children[i]) - width)).toBeLessThan 1
|
||||
expect(wrapGuide).toBeVisible()
|
||||
|
||||
describe "when the font size changes", ->
|
||||
it "updates the wrap guide position", ->
|
||||
initial = getLeftPosition(wrapGuide.firstChild)
|
||||
expect(initial).toBeGreaterThan(0)
|
||||
fontSize = atom.config.get("editor.fontSize")
|
||||
atom.config.set("editor.fontSize", fontSize + 10)
|
||||
|
||||
waitsForPromise ->
|
||||
editorElement.getComponent().getNextUpdatePromise()
|
||||
|
||||
runs ->
|
||||
expect(getLeftPosition(wrapGuide.firstChild)).toBeGreaterThan(initial)
|
||||
expect(wrapGuide.firstChild).toBeVisible()
|
||||
|
||||
it "updates the wrap guide position for hidden editors when they become visible", ->
|
||||
initial = getLeftPosition(wrapGuide.firstChild)
|
||||
expect(initial).toBeGreaterThan(0)
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open()
|
||||
|
||||
runs ->
|
||||
fontSize = atom.config.get("editor.fontSize")
|
||||
atom.config.set("editor.fontSize", fontSize + 10)
|
||||
atom.workspace.getActivePane().activatePreviousItem()
|
||||
|
||||
waitsForPromise ->
|
||||
editorElement.getComponent().getNextUpdatePromise()
|
||||
|
||||
runs ->
|
||||
expect(getLeftPosition(wrapGuide.firstChild)).toBeGreaterThan(initial)
|
||||
expect(wrapGuide.firstChild).toBeVisible()
|
||||
|
||||
describe "when the column config changes", ->
|
||||
it "updates the wrap guide position", ->
|
||||
initial = getLeftPosition(wrapGuide.firstChild)
|
||||
expect(initial).toBeGreaterThan(0)
|
||||
column = atom.config.get("editor.preferredLineLength")
|
||||
atom.config.set("editor.preferredLineLength", column + 10)
|
||||
expect(getLeftPosition(wrapGuide.firstChild)).toBeGreaterThan(initial)
|
||||
expect(wrapGuide).toBeVisible()
|
||||
|
||||
describe "when the preferredLineLength changes", ->
|
||||
it "updates the wrap guide positions", ->
|
||||
initial = [10, 15, 20, 30]
|
||||
atom.config.set 'wrap-guide.columns', initial,
|
||||
scopeSelector: ".#{editor.getGrammar().scopeName}"
|
||||
waitsForPromise ->
|
||||
editorElement.getComponent().getNextUpdatePromise()
|
||||
|
||||
runs ->
|
||||
atom.config.set 'editor.preferredLineLength', 15,
|
||||
scopeSelector: ".#{editor.getGrammar().scopeName}"
|
||||
waitsForPromise ->
|
||||
editorElement.getComponent().getNextUpdatePromise()
|
||||
|
||||
runs ->
|
||||
columns = atom.config.get('wrap-guide.columns', scope: editor.getRootScopeDescriptor())
|
||||
expect(columns.length).toBe(2)
|
||||
expect(columns[0]).toBe(10)
|
||||
expect(columns[1]).toBe(15)
|
||||
|
||||
describe "when the columns config changes", ->
|
||||
it "updates the wrap guide positions", ->
|
||||
initial = getLeftPositions(wrapGuide.children)
|
||||
expect(initial.length).toBe(1)
|
||||
expect(initial[0]).toBeGreaterThan(0)
|
||||
|
||||
columns = [10, 20, 30]
|
||||
atom.config.set("wrap-guide.columns", columns)
|
||||
waitsForPromise ->
|
||||
editorElement.getComponent().getNextUpdatePromise()
|
||||
|
||||
runs ->
|
||||
positions = getLeftPositions(wrapGuide.children)
|
||||
expect(positions.length).toBe(columns.length)
|
||||
expect(positions[0]).toBeGreaterThan(0)
|
||||
expect(positions[1]).toBeGreaterThan(positions[0])
|
||||
expect(positions[2]).toBeGreaterThan(positions[1])
|
||||
expect(wrapGuide).toBeVisible()
|
||||
|
||||
it "updates the preferredLineLength", ->
|
||||
initial = atom.config.get('editor.preferredLineLength', scope: editor.getRootScopeDescriptor())
|
||||
atom.config.set("wrap-guide.columns", [initial, initial + 10])
|
||||
waitsForPromise ->
|
||||
editorElement.getComponent().getNextUpdatePromise()
|
||||
|
||||
runs ->
|
||||
length = atom.config.get('editor.preferredLineLength', scope: editor.getRootScopeDescriptor())
|
||||
expect(length).toBe(initial + 10)
|
||||
|
||||
it "keeps guide positions unique and in ascending order", ->
|
||||
initial = getLeftPositions(wrapGuide.children)
|
||||
expect(initial.length).toBe(1)
|
||||
expect(initial[0]).toBeGreaterThan(0)
|
||||
|
||||
reverseColumns = [30, 20, 10]
|
||||
columns = [reverseColumns[reverseColumns.length - 1], reverseColumns..., reverseColumns[0]]
|
||||
uniqueColumns = uniqueAscending(columns)
|
||||
expect(uniqueColumns.length).toBe(3)
|
||||
expect(uniqueColumns[0]).toBeGreaterThan(0)
|
||||
expect(uniqueColumns[1]).toBeGreaterThan(uniqueColumns[0])
|
||||
expect(uniqueColumns[2]).toBeGreaterThan(uniqueColumns[1])
|
||||
|
||||
atom.config.set("wrap-guide.columns", columns)
|
||||
waitsForPromise ->
|
||||
editorElement.getComponent().getNextUpdatePromise()
|
||||
|
||||
runs ->
|
||||
positions = getLeftPositions(wrapGuide.children)
|
||||
expect(positions.length).toBe(uniqueColumns.length)
|
||||
expect(positions[0]).toBeGreaterThan(0)
|
||||
expect(positions[1]).toBeGreaterThan(positions[0])
|
||||
expect(positions[2]).toBeGreaterThan(positions[1])
|
||||
expect(wrapGuide).toBeVisible()
|
||||
|
||||
describe "when the editor's scroll left changes", ->
|
||||
it "updates the wrap guide position to a relative position on screen", ->
|
||||
editor.setText("a long line which causes the editor to scroll")
|
||||
editorElement.style.width = "100px"
|
||||
|
||||
waitsFor -> editorElement.component.getMaxScrollLeft() > 10
|
||||
|
||||
runs ->
|
||||
initial = getLeftPosition(wrapGuide.firstChild)
|
||||
expect(initial).toBeGreaterThan(0)
|
||||
editorElement.setScrollLeft(10)
|
||||
expect(getLeftPosition(wrapGuide.firstChild)).toBe(initial - 10)
|
||||
expect(wrapGuide.firstChild).toBeVisible()
|
||||
|
||||
describe "when the editor's grammar changes", ->
|
||||
it "updates the wrap guide position", ->
|
||||
atom.config.set('editor.preferredLineLength', 20, scopeSelector: '.source.js')
|
||||
initial = getLeftPosition(wrapGuide.firstChild)
|
||||
expect(initial).toBeGreaterThan(0)
|
||||
expect(wrapGuide).toBeVisible()
|
||||
|
||||
editor.setGrammar(atom.grammars.grammarForScopeName('text.plain.null-grammar'))
|
||||
expect(getLeftPosition(wrapGuide.firstChild)).toBeGreaterThan(initial)
|
||||
expect(wrapGuide).toBeVisible()
|
||||
|
||||
it 'listens for preferredLineLength updates for the new grammar', ->
|
||||
editor.setGrammar(atom.grammars.grammarForScopeName('source.coffee'))
|
||||
initial = getLeftPosition(wrapGuide.firstChild)
|
||||
atom.config.set('editor.preferredLineLength', 20, scopeSelector: '.source.coffee')
|
||||
expect(getLeftPosition(wrapGuide.firstChild)).toBeLessThan(initial)
|
||||
|
||||
it 'listens for wrap-guide.enabled updates for the new grammar', ->
|
||||
editor.setGrammar(atom.grammars.grammarForScopeName('source.coffee'))
|
||||
expect(wrapGuide).toBeVisible()
|
||||
atom.config.set('wrap-guide.enabled', false, scopeSelector: '.source.coffee')
|
||||
expect(wrapGuide).not.toBeVisible()
|
||||
|
||||
describe 'scoped config', ->
|
||||
it '::getDefaultColumn returns the scope-specific column value', ->
|
||||
atom.config.set('editor.preferredLineLength', 132, scopeSelector: '.source.js')
|
||||
|
||||
expect(wrapGuide.getDefaultColumn()).toBe 132
|
||||
|
||||
it 'updates the guide when the scope-specific column changes', ->
|
||||
initial = getLeftPosition(wrapGuide.firstChild)
|
||||
column = atom.config.get('editor.preferredLineLength', scope: editor.getRootScopeDescriptor())
|
||||
atom.config.set('editor.preferredLineLength', column + 10, scope: '.source.js')
|
||||
expect(getLeftPosition(wrapGuide.firstChild)).toBeGreaterThan(initial)
|
||||
|
||||
it 'updates the guide when wrap-guide.enabled is set to false', ->
|
||||
expect(wrapGuide).toBeVisible()
|
||||
|
||||
atom.config.set('wrap-guide.enabled', false, scopeSelector: '.source.js')
|
||||
|
||||
expect(wrapGuide).not.toBeVisible()
|
48
packages/wrap-guide/spec/wrap-guide-spec.js
Normal file
48
packages/wrap-guide/spec/wrap-guide-spec.js
Normal file
@ -0,0 +1,48 @@
|
||||
const {getWrapGuides, getLeftPosition} = require('./helpers')
|
||||
|
||||
const {it, fit, ffit, afterEach, beforeEach} = require('./async-spec-helpers') // eslint-disable-line no-unused-vars
|
||||
|
||||
describe('Wrap Guide', () => {
|
||||
let editor, editorElement, wrapGuide = []
|
||||
|
||||
beforeEach(async () => {
|
||||
await atom.packages.activatePackage('wrap-guide')
|
||||
|
||||
editor = await atom.workspace.open('sample.js')
|
||||
editorElement = editor.getElement()
|
||||
wrapGuide = editorElement.querySelector('.wrap-guide-container')
|
||||
|
||||
jasmine.attachToDOM(atom.views.getView(atom.workspace))
|
||||
})
|
||||
|
||||
describe('package activation', () => {
|
||||
it('appends a wrap guide to all existing and new editors', () => {
|
||||
expect(atom.workspace.getTextEditors().length).toBe(1)
|
||||
expect(getWrapGuides().length).toBe(1)
|
||||
expect(getLeftPosition(getWrapGuides()[0])).toBeGreaterThan(0)
|
||||
|
||||
atom.workspace.getActivePane().splitRight({copyActiveItem: true})
|
||||
expect(atom.workspace.getTextEditors().length).toBe(2)
|
||||
expect(getWrapGuides().length).toBe(2)
|
||||
expect(getLeftPosition(getWrapGuides()[0])).toBeGreaterThan(0)
|
||||
expect(getLeftPosition(getWrapGuides()[1])).toBeGreaterThan(0)
|
||||
})
|
||||
|
||||
it('positions the guide at the configured column', () => {
|
||||
width = editor.getDefaultCharWidth() * wrapGuide.getDefaultColumn()
|
||||
expect(width).toBeGreaterThan(0)
|
||||
expect(Math.abs(getLeftPosition(wrapGuide.firstChild) - width)).toBeLessThan(1)
|
||||
expect(wrapGuide.firstChild).toBeVisible()
|
||||
})
|
||||
})
|
||||
|
||||
describe('package deactivation', () => {
|
||||
beforeEach(async () => {
|
||||
await atom.packages.deactivatePackage('wrap-guide')
|
||||
})
|
||||
|
||||
it('disposes of all wrap guides', () => {
|
||||
expect(getWrapGuides().length).toBe(0)
|
||||
})
|
||||
})
|
||||
})
|
14
packages/wrap-guide/styles/wrap-guide.less
Normal file
14
packages/wrap-guide/styles/wrap-guide.less
Normal file
@ -0,0 +1,14 @@
|
||||
@import "syntax-variables";
|
||||
|
||||
atom-text-editor {
|
||||
.wrap-guide {
|
||||
height: 100%;
|
||||
width: 1px;
|
||||
z-index: 3;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
background-color: @syntax-wrap-guide-color;
|
||||
-webkit-transform: translateZ(0);
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
@ -10097,9 +10097,8 @@ wrap-ansi@^7.0.0:
|
||||
string-width "^4.1.0"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
"wrap-guide@https://codeload.github.com/atom/wrap-guide/legacy.tar.gz/refs/tags/v0.41.0":
|
||||
"wrap-guide@file:./packages/wrap-guide":
|
||||
version "0.41.0"
|
||||
resolved "https://codeload.github.com/atom/wrap-guide/legacy.tar.gz/refs/tags/v0.41.0#bd23ce8c207d589c742bd324135de81b6eb7ec02"
|
||||
|
||||
wrappy@1:
|
||||
version "1.0.2"
|
||||
|
Loading…
Reference in New Issue
Block a user