Skip to content
This repository has been archived by the owner on Dec 15, 2022. It is now read-only.

Package rewrite #309

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion .coffeelintignore

This file was deleted.

43 changes: 43 additions & 0 deletions available-snippets-view.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
const SelectListView = require('atom-select-list')

module.exports = class AvailableSnippetsView extends SelectListView {
constructor (snippets, editor) {
super({
items: Object.entries(snippets.snippetsByScopes()
.getPropertyValue(editor.getRootScopeDescriptor().getScopeChain())),
filterKeyForItem: ([name, { prefix }]) => prefix + name,
elementForItem: ([name, { prefix, description }]) => {
const li = document.createElement('li')
li.classList.add('two-lines')

const primaryLine = li.appendChild(document.createElement('div'))
primaryLine.classList.add('primary-line')
primaryLine.textContent = prefix

const secondaryLine = li.appendChild(document.createElement('div'))
secondaryLine.classList.add('secondary-line')
// TODO: Nullish coalescing operator
secondaryLine.textContent = description != null ? description : name

return li
},
emptyMessage: 'No snippets defined for this Grammar.',
itemsClassList: ['available-snippets'],
didConfirmSelection: ([, { body }]) => {
this.destroy()
editor.getCursors().forEach(cursor =>
snippets.parse(body).expand({ editor, cursor }))
},
didConfirmEmptySelection: () => this.destroy(),
didCancelSelection: () => this.destroy()
})

const panel = atom.workspace.addModalPanel({ item: this })
this.disposables.add(
// Register cleanup disposables to be called on desctruction
{ dispose: () => document.activeElement.focus },
{ dispose: () => { panel.destroy() } })

this.focus()
}
}
6 changes: 6 additions & 0 deletions babel.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"plugins": [
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-private-methods"
]
}
37 changes: 0 additions & 37 deletions coffeelint.json

This file was deleted.

6 changes: 6 additions & 0 deletions expression/babel.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"plugins": [
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-private-methods"
]
}
60 changes: 60 additions & 0 deletions expression/choice.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
const { CompositeDisposable } = require('atom')

const Expression = require('./expression')

module.exports = class Choice extends Expression {
constructor (identifier, choices) {
super(identifier)

this.choices = choices
// The "first" and therefore default values is last in the list so that
// choice cycling starts from the second choice
this.default = choices[choices.length - 1]
}

activate (editor, cursor, stop, mirror) {
super.activate(editor, cursor, stop, mirror)
// Don't bother if a mirror, the marker won't get iterated over
if (mirror === stop) {
const disposables = new CompositeDisposable()

const target = 'atom-text-editor:not([mini])'
const cycle = `snippets:next-choice-${stop.id}`

const choices = {
choices: this.choices,
iterator: this.choices.values(),
next () {
const iteration = this.iterator.next()
const { value } = iteration.done
? (this.iterator = this.choices.values()).next()
: iteration
editor.getBuffer().setTextInRange(stop.getBufferRange(), value)
cursor.selection.setBufferRange(stop.getBufferRange())
}
}

// What happens when the user clicks inside the choice, resulting in it nolonger being selected
disposables.add(
atom.keymaps.add(module.filename, { [target]: { 'shift-tab': cycle } }),
atom.commands.add(target, cycle, event => choices.next()),
cursor.onDidChangePosition(({ newBufferPosition }) => {
if (!stop.getBufferRange().containsPoint(newBufferPosition)) {
disposables.dispose()
}
}))
}
}

expand (editor, cursor, tabstops, variables) {
if (!(this.identifier in variables)) {
this.mark({ tabstops, ...this.insert(editor, cursor, this.default) })
} else {
super.expand(editor, cursor, tabstops, variables)
}
}

toString () {
return this.default.toString()
}
}
45 changes: 45 additions & 0 deletions expression/expression.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
module.exports = class Expression {
constructor (identifier) {
this.identifier = identifier
}

expand (editor, cursor, tabstops, variables) {
// Check whether we are a tabstop or a variable
Number.isInteger(this.identifier)
// Create a tabstop marker at our position
? this.mark({ tabstops, start: cursor.getBufferPosition() })
// Check whether we are a know variable or not
: this.identifier in variables
// Insert the variables value
? this.insert(editor, cursor, variables[this.identifier])
// Insert 'this.identifier' and create a tabstop marker with it selected
: this.mark({ tabstops, ...this.insert(editor, cursor, this.identifier) })
}

insert (editor, cursor, value) {
return editor.getBuffer().insert(cursor.getBufferPosition(), value)
}

activate (editor, cursor, stop, mirror) {
if (mirror === stop) {
cursor.selection.setBufferRange(stop.getBufferRange())
const subscription = cursor.onDidChangePosition(({ newBufferPosition }) => {
if (!stop.getBufferRange().containsPoint(newBufferPosition)) {
stop.destroy()
subscription.dispose()
}
})
} else {
editor.decorateMarker(mirror, { type: 'highlight' })
stop.onDidDestroy(() => mirror.destroy())
}
}

mark ({ tabstops, start, end = start, exclusive = true, expression = this }) {
tabstops.markBufferRange({ start, end }, { exclusive }).setProperties({ expression })
}

toString () {
return ''
}
}
21 changes: 21 additions & 0 deletions expression/placeholder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const Expression = require('./expression')

module.exports = class Placeholder extends Expression {
constructor (identifier, snippet) {
super(identifier)

this.snippet = snippet
}

expand (editor, cursor, tabstops, variables) {
if (!(this.identifier in variables)) {
this.mark({ tabstops, ...this.snippet.expand({ editor, cursor, tabstops, variables }) })
} else {
super.expand(editor, cursor, tabstops, variables)
}
}

toString () {
return this.snippet.toString()
}
}