Skip to content
This repository was archived by the owner on Jan 8, 2025. It is now read-only.

Commit 0bbbeac

Browse files
Merge branch 'master' into cleanup-and-master
2 parents 4b9d45c + 12eec6d commit 0bbbeac

File tree

16 files changed

+2260
-362
lines changed

16 files changed

+2260
-362
lines changed

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.pegjs

.eslintrc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"parserOptions": {
3+
"sourceType": "module",
4+
"ecmaVersion": 2022
5+
},
6+
"rules": {
7+
"indent": ["error", 2],
8+
"linebreak-style": ["error", "unix"],
9+
"object-curly-spacing": ["error", "never"],
10+
"space-before-function-paren": ["error", "always"],
11+
"semi": ["error", "never"]
12+
}
13+
}

.github/workflows/pulsar_test.yml

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,17 @@ jobs:
1414
- name: Checkout the Latest Package Code
1515
uses: actions/checkout@v3
1616
- name: Setup Pulsar Editor
17-
uses: pulsar-edit/[email protected]
18-
with:
19-
package-to-test: "snippets"
17+
uses: pulsar-edit/[email protected]
18+
- name: Install dependencies (Windows)
19+
if: ${{ runner.os == 'Windows' }}
20+
# Currently the Pulsar process starts, but unlike *nix doesn't wait for ppm to finish, probably because pulsar.cmd needs updated
21+
# So we'll fallback to ppm (still named apm) instead
22+
run: apm install
23+
- name: Install dependencies (*nix)
24+
if: ${{ runner.os != 'Windows' }}
25+
run: pulsar --package install
2026
- name: Run the headless Pulsar Tests
21-
uses: GabrielBB/xvfb-action@v1
27+
uses: coactions/setup-xvfb@v1.0.1
2228
with:
23-
run: yarn start --test spec
24-
working-directory: ./pulsar
29+
run: pulsar --test spec
30+
# working-directory: ./pulsar

README.md

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,46 @@ Snippets files are stored in a package's `snippets/` folder and also loaded from
1212
'.source.js':
1313
'console.log':
1414
'prefix': 'log'
15+
'command': 'insert-console-log'
1516
'body': 'console.log(${1:"crash"});$2'
1617
```
1718

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

2021
The next level of keys are the snippet names.
2122

22-
Under each snippet name is a `prefix` that should trigger the snippet and a `body` to insert when the snippet is triggered.
23+
Under each snippet name is a `body` to insert when the snippet is triggered.
2324

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

26-
The above example adds a `log` snippet to JavaScript files that would expand to.
27+
The above example adds a `console.log` snippet to JavaScript files that would expand to:
2728

2829
```js
2930
console.log("crash");
3031
```
3132

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

35+
A snippet must define **at least one** of the following keys:
36+
37+
### The ‘prefix’ key
38+
39+
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.
40+
41+
Prefix completions can be suggested if partially typed thanks to the `autocomplete-snippets` package.
42+
43+
### The ‘command’ key
44+
45+
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`.
46+
47+
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`.
48+
49+
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”.
50+
51+
Invoking the command would insert the snippet at the cursor, replacing any text that may be selected.
52+
3453
### Optional parameters
54+
3555
These parameters are meant to provide extra information about your snippet to [autocomplete-plus](https://github.com/atom/autocomplete-plus/wiki/Provider-API).
3656

3757
* `leftLabel` will add text to the left part of the autocomplete results box.

lib/editor-store.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ class EditorStore {
2727
}
2828

2929
observeHistory (delegates) {
30-
if (this.existingHistoryProvider == null) {
30+
let isObservingHistory = this.existingHistoryProvider != null
31+
if (isObservingHistory) {
32+
return
33+
} else {
3134
this.existingHistoryProvider = this.buffer.historyProvider
3235
}
3336

lib/snippet-body.pegjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ variableContentChar = !variable char:('\\}' / [^}]) { return char; }
6363
escapedForwardSlash = pair:'\\/' { return pair; }
6464

6565
// A pattern and replacement for a transformed tab stop.
66-
transformationSubstitution = '/' find:(escapedForwardSlash / [^/])* '/' replace:formatString* '/' flags:[imy]* {
67-
let reFind = new RegExp(find.join(''), flags.join('') + 'g');
66+
transformationSubstitution = '/' find:(escapedForwardSlash / [^/])* '/' replace:formatString* '/' flags:[gimy]* {
67+
let reFind = new RegExp(find.join(''), flags.join(''));
6868
return { find: reFind, replace: replace[0] };
6969
}
7070

lib/snippet-expansion.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const {CompositeDisposable, Range, Point} = require('atom')
22

33
module.exports = class SnippetExpansion {
4-
constructor(snippet, editor, cursor, snippets) {
4+
constructor (snippet, editor, cursor, snippets) {
55
this.settingTabStop = false
66
this.isIgnoringBufferChanges = false
77
this.onUndoOrRedo = this.onUndoOrRedo.bind(this)
@@ -175,7 +175,7 @@ module.exports = class SnippetExpansion {
175175
const marker = this.getMarkerLayer(this.editor).markBufferRange([
176176
startPosition.traverse(start),
177177
startPosition.traverse(end)
178-
], { exclusive: !shouldBeInclusive })
178+
], {exclusive: !shouldBeInclusive})
179179
// Now that we've created these markers, we need to store them in a
180180
// data structure because they'll need to be deleted and re-created
181181
// when their exclusivity changes.
@@ -354,7 +354,7 @@ module.exports = class SnippetExpansion {
354354
if (lastMarker.isDestroyed()) {
355355
return false
356356
} else {
357-
this.seditor.setCursorBufferPosition(lastMarker.getEndBufferPosition())
357+
this.editor.setCursorBufferPosition(lastMarker.getEndBufferPosition())
358358
return true
359359
}
360360
}
@@ -364,7 +364,7 @@ module.exports = class SnippetExpansion {
364364
this.getMarkerLayer(this.editor).clear()
365365
this.insertionsByIndex = []
366366
this.relatedInsertionsByIndex = new Map()
367-
this.markersForInsertions = new Map();
367+
this.markersForInsertions = new Map()
368368
this.snippets.stopObservingEditor(this.editor)
369369
this.snippets.clearExpansions(this.editor)
370370
}

lib/snippet.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,23 @@ function tabStopsReferencedWithinTabStopContent (segment) {
1212
}
1313

1414
module.exports = class Snippet {
15-
constructor({name, prefix, bodyText, description, descriptionMoreURL, rightLabelHTML, leftLabel, leftLabelHTML, bodyTree}) {
15+
constructor ({name, prefix, command, bodyText, description, packageName, descriptionMoreURL, rightLabelHTML, leftLabel, leftLabelHTML, bodyTree, selector}) {
1616
this.name = name
1717
this.prefix = prefix
18+
this.command = command
19+
this.packageName = packageName
1820
this.bodyText = bodyText
1921
this.description = description
2022
this.descriptionMoreURL = descriptionMoreURL
2123
this.rightLabelHTML = rightLabelHTML
2224
this.leftLabel = leftLabel
2325
this.leftLabelHTML = leftLabelHTML
26+
this.selector = selector
2427
this.tabStopList = new TabStopList(this)
2528
this.body = this.extractTabStops(bodyTree)
29+
if (packageName && command) {
30+
this.commandName = `${packageName}:${command}`
31+
}
2632
}
2733

2834
extractTabStops (bodyTree) {
@@ -35,10 +41,14 @@ module.exports = class Snippet {
3541
for (const segment of bodyTree) {
3642
if (segment.index != null) {
3743
let {index, content, substitution} = segment
38-
if (index === 0) { index = Infinity; }
44+
// Ensure tabstop `$0` is always last.
45+
if (index === 0) { index = Infinity }
46+
3947
const start = [row, column]
4048
extractTabStops(content)
49+
4150
const referencedTabStops = tabStopsReferencedWithinTabStopContent(content)
51+
4252
const range = new Range(start, [row, column])
4353
const tabStop = this.tabStopList.findOrCreate({
4454
index,

0 commit comments

Comments
 (0)