Skip to content
This repository was archived by the owner on Jan 8, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.pegjs
13 changes: 13 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"parserOptions": {
"sourceType": "module",
"ecmaVersion": 2022
},
"rules": {
"indent": ["error", 2],
"linebreak-style": ["error", "unix"],
"object-curly-spacing": ["error", "never"],
"space-before-function-paren": ["error", "always"],
"semi": ["error", "never"]
}
}
18 changes: 12 additions & 6 deletions .github/workflows/pulsar_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,17 @@ jobs:
- name: Checkout the Latest Package Code
uses: actions/checkout@v3
- name: Setup Pulsar Editor
uses: pulsar-edit/[email protected]
with:
package-to-test: "snippets"
uses: pulsar-edit/action-pulsar-dependency@s985-update-win-path-registration
- name: Install dependencies (Windows)
if: ${{ runner.os == 'Windows' }}
# Currently the Pulsar process starts, but unlike *nix doesn't wait for ppm to finish, probably because pulsar.cmd needs updated
# So we'll fallback to ppm (still named apm) instead
run: apm install
- name: Install dependencies (*nix)
if: ${{ runner.os != 'Windows' }}
run: pulsar --package install
- name: Run the headless Pulsar Tests
uses: GabrielBB/xvfb-action@v1
uses: GabrielBB/xvfb-action@v1.6
with:
run: yarn start --test spec
working-directory: ./pulsar
run: pulsar --test spec
# working-directory: ./pulsar
26 changes: 23 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,46 @@ Snippets files are stored in a package's `snippets/` folder and also loaded from
'.source.js':
'console.log':
'prefix': 'log'
'command': 'insert-console-log'
'body': 'console.log(${1:"crash"});$2'
```

The outermost keys are the selectors where these snippets should be active, prefixed with a period (`.`) (details below).

The next level of keys are the snippet names.

Under each snippet name is a `prefix` that should trigger the snippet and a `body` to insert when the snippet is triggered.
Under each snippet name is a `body` to insert when the snippet is triggered.

`$` followed by a number are the tabs stops which can be cycled between by pressing <kbd>tab</kbd> once a snippet has been triggered.
`$` followed by a number are the tabs stops which can be cycled between by pressing <kbd>Tab</kbd> once a snippet has been triggered.

The above example adds a `log` snippet to JavaScript files that would expand to.
The above example adds a `console.log` snippet to JavaScript files that would expand to:

```js
console.log("crash");
```

The string `"crash"` would be initially selected and pressing tab again would place the cursor after the `;`

A snippet must define **at least one** of the following keys:

### The ‘prefix’ key

If a `prefix` is defined, it specifies a string that can trigger the snippet: type the string in the editor and press <kbd>Tab</kbd>. In this example, typing `log` (as its own word) and then pressing <kbd>Tab</kbd> would replace `log` with the string `console.log("crash")` as described above.

Prefix completions can be suggested if partially typed thanks to the `autocomplete-snippets` package.

### The ‘command’ key

If a `command` is defined, it specifies a command name that can trigger the snippet. That command can be invoked from the command palette or mapped to a keyboard shortcut via your `keymap.cson`.

If you defined the `console.log` snippet described above in your own `snippets.cson`, it would be available in the command palette as “Snippets: Insert Console Log”, or could be referenced in a keymap file as `snippets:insert-console-log`.

If a package called `some-package` had defined that snippet, it would be available in the keymap as `some-package:insert-console-log`, or in the command palette as “Some Package: Insert Console Log”.

Invoking the command would insert the snippet at the cursor, replacing any text that may be selected.

### Optional parameters

These parameters are meant to provide extra information about your snippet to [autocomplete-plus](https://github.com/atom/autocomplete-plus/wiki/Provider-API).

* `leftLabel` will add text to the left part of the autocomplete results box.
Expand Down
5 changes: 4 additions & 1 deletion lib/editor-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ class EditorStore {
}

observeHistory (delegates) {
if (this.existingHistoryProvider == null) {
let isObservingHistory = this.existingHistoryProvider != null
if (isObservingHistory) {
return
} else {
this.existingHistoryProvider = this.buffer.historyProvider
}

Expand Down
6 changes: 3 additions & 3 deletions lib/snippet-expansion.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const {CompositeDisposable, Range, Point} = require('atom')

module.exports = class SnippetExpansion {
constructor(snippet, editor, cursor, snippets) {
constructor (snippet, editor, cursor, snippets) {
this.settingTabStop = false
this.isIgnoringBufferChanges = false
this.onUndoOrRedo = this.onUndoOrRedo.bind(this)
Expand Down Expand Up @@ -175,7 +175,7 @@ module.exports = class SnippetExpansion {
const marker = this.getMarkerLayer(this.editor).markBufferRange([
startPosition.traverse(start),
startPosition.traverse(end)
], { exclusive: !shouldBeInclusive })
], {exclusive: !shouldBeInclusive})
// Now that we've created these markers, we need to store them in a
// data structure because they'll need to be deleted and re-created
// when their exclusivity changes.
Expand Down Expand Up @@ -364,7 +364,7 @@ module.exports = class SnippetExpansion {
this.getMarkerLayer(this.editor).clear()
this.insertionsByIndex = []
this.relatedInsertionsByIndex = new Map()
this.markersForInsertions = new Map();
this.markersForInsertions = new Map()
this.snippets.stopObservingEditor(this.editor)
this.snippets.clearExpansions(this.editor)
}
Expand Down
14 changes: 12 additions & 2 deletions lib/snippet.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,23 @@ function tabStopsReferencedWithinTabStopContent (segment) {
}

module.exports = class Snippet {
constructor({name, prefix, bodyText, description, descriptionMoreURL, rightLabelHTML, leftLabel, leftLabelHTML, bodyTree}) {
constructor ({name, prefix, command, bodyText, description, packageName, descriptionMoreURL, rightLabelHTML, leftLabel, leftLabelHTML, bodyTree, selector}) {
this.name = name
this.prefix = prefix
this.command = command
this.packageName = packageName
this.bodyText = bodyText
this.description = description
this.descriptionMoreURL = descriptionMoreURL
this.rightLabelHTML = rightLabelHTML
this.leftLabel = leftLabel
this.leftLabelHTML = leftLabelHTML
this.selector = selector
this.tabStopList = new TabStopList(this)
this.body = this.extractTabStops(bodyTree)
if (packageName && command) {
this.commandName = `${packageName}:${command}`
}
}

extractTabStops (bodyTree) {
Expand All @@ -35,10 +41,14 @@ module.exports = class Snippet {
for (const segment of bodyTree) {
if (segment.index != null) {
let {index, content, substitution} = segment
if (index === 0) { index = Infinity; }
// Ensure tabstop `$0` is always last.
if (index === 0) { index = Infinity }

const start = [row, column]
extractTabStops(content)

const referencedTabStops = tabStopsReferencedWithinTabStopContent(content)

const range = new Range(start, [row, column])
const tabStop = this.tabStopList.findOrCreate({
index,
Expand Down
Loading