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

Expansion of nested snippets #192

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 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
11 changes: 9 additions & 2 deletions lib/snippet-expansion.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,14 @@ class SnippetExpansion
false

goToPreviousTabStop: ->
@setTabStopIndex(@tabStopIndex - 1) if @tabStopIndex > 0
if @tabStopIndex > 0
if @setTabStopIndex(@tabStopIndex - 1)
true
else
@goToPreviousTabStop()
else
@destroy()
false

setTabStopIndex: (@tabStopIndex) ->
@settingTabStop = true
Expand Down Expand Up @@ -84,7 +91,7 @@ class SnippetExpansion
for markers in @tabStopMarkers
marker.destroy() for marker in markers
@tabStopMarkers = []
@snippets.clearExpansions(@editor)
@snippets.clearCurrentExpansions(@editor)

restore: (@editor) ->
@snippets.addExpansion(@editor, this)
36 changes: 27 additions & 9 deletions lib/snippets.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ module.exports =
'snippets:expand': (event) ->
editor = @getModel()
if snippets.snippetToExpandUnderCursor(editor)
snippets.clearExpansions(editor)
snippets.newCurrentExpansions(editor)
snippets.expandSnippetsUnderCursors(editor)
else
event.abortKeyBinding()
Expand Down Expand Up @@ -306,27 +306,45 @@ module.exports =

goToNextTabStop: (editor) ->
nextTabStopVisited = false
for expansion in @getExpansions(editor)
if expansion?.goToNextTabStop()
nextTabStopVisited = true
while currentExpansions = @getCurrentExpansions(editor)
@clearCurrentExpansions(editor) unless currentExpansions.length
for expansion in currentExpansions
if expansion?.goToNextTabStop()
nextTabStopVisited = true
break if nextTabStopVisited
nextTabStopVisited

goToPreviousTabStop: (editor) ->
previousTabStopVisited = false
for expansion in @getExpansions(editor)
if expansion?.goToPreviousTabStop()
previousTabStopVisited = true
while currentExpansions = @getCurrentExpansions(editor)
@clearCurrentExpansions(editor) unless currentExpansions.length
for expansion in currentExpansions
if expansion?.goToPreviousTabStop()
previousTabStopVisited = true
break if previousTabStopVisited
previousTabStopVisited

getExpansions: (editor) ->
@editorSnippetExpansions?.get(editor) ? []
@editorSnippetExpansions.get(editor)

getCurrentExpansions: (editor) ->
expansions = @getExpansions(editor)
return expansions[expansions.length - 1] if expansions.length

clearExpansions: (editor) ->
@editorSnippetExpansions ?= new WeakMap()
@editorSnippetExpansions.set(editor, [])

clearCurrentExpansions: (editor) ->
expansions = @getExpansions(editor)
expansions.pop() if expansions.length

addExpansion: (editor, snippetExpansion) ->
@getExpansions(editor).push(snippetExpansion)
if not @getCurrentExpansions(editor)?.push(snippetExpansion)
@getExpansions(editor).push([snippetExpansion])

newCurrentExpansions: (editor) ->
@getExpansions(editor).push([])

insert: (snippet, editor=atom.workspace.getActiveTextEditor(), cursor=editor.getLastCursor()) ->
if typeof snippet is 'string'
Expand Down
41 changes: 37 additions & 4 deletions spec/snippets-spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -267,10 +267,6 @@ describe "Snippets extension", ->
simulateTabKeyEvent(shift: true)
expect(editor.getSelectedBufferRange()).toEqual [[3, 15], [3, 15]]

# shift-tab on first tab-stop does nothing
simulateTabKeyEvent(shift: true)
expect(editor.getCursorScreenPosition()).toEqual [3, 15]

# tab through all tab stops, then tab on last stop to terminate snippet
simulateTabKeyEvent()
simulateTabKeyEvent()
Expand Down Expand Up @@ -655,6 +651,43 @@ describe "Snippets extension", ->
expect(editor.lineTextForBufferRow(7)).toBe " }one t1 three"
expect(editor.lineTextForBufferRow(12)).toBe "};one t1 three"

describe "when there are nested snippets", ->
it "tries to expand before moving to the next tabstop", ->
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test fails. The keybindings are resolved in the wrong order, but only in tests, it works in real life. This is the reason that the next test fails too.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused about the current intended behaviour when a snippet is triggered within an existing expansion. According to the specs, it should go to the next tabstop without expanding, but according to the keymaps (snippets-1.cson and snippets-2.cson), it should try to expand first. When I try it myself, it expands most of the times, but not always.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would make sense to attempt to expand first if possible.

spyOn(Snippets, 'snippetToExpandUnderCursor').andReturn(false)
spyOn(Snippets, 'goToNextTabStop').andReturn(true)

simulateTabKeyEvent()
expect(Snippets.snippetToExpandUnderCursor).toHaveBeenCalled()
expect(Snippets.goToNextTabStop).toHaveBeenCalled()

it "moves to surrounding expansions after terminating a snippet", ->
editor.setText 't2'
editor.setCursorScreenPosition [0, 2]
simulateTabKeyEvent()
editor.insertText 't2'
simulateTabKeyEvent()
expect(editor.lineTextForBufferRow(0)).toBe "go here next:() and finally go here:()"
expect(editor.lineTextForBufferRow(1)).toBe "go here first:(go here next:() and finally go here:()"
expect(editor.lineTextForBufferRow(2)).toBe "go here first:())"
expect(editor.getSelectedBufferRange()).toEqual [[2, 15], [2, 15]]

simulateTabKeyEvent()
simulateTabKeyEvent()
editor.insertText 't5'
simulateTabKeyEvent()
simulateTabKeyEvent(shift: true)
expect(editor.lineTextForBufferRow(1)).toBe 'go here first:(go here next:() and finally go here:("key": value)'
expect(editor.getSelectedBufferRange()).toEqual [[1, 29], [1, 29]]

simulateTabKeyEvent()
simulateTabKeyEvent()
expect(editor.lineTextForBufferRow(0)).toBe "go here next:() and finally go here:()"
expect(editor.getSelectedBufferRange()).toEqual [[0, 14], [0, 14]]

simulateTabKeyEvent()
simulateTabKeyEvent()
expect(editor.lineTextForBufferRow(0)).toBe "go here next:() and finally go here:( )"

describe "when atom://.atom/snippets is opened", ->
it "opens ~/.atom/snippets.cson", ->
jasmine.unspy(Snippets, 'getUserSnippetsPath')
Expand Down