Skip to content
This repository has been archived by the owner on Apr 1, 2020. It is now read-only.

Add indents to every line in the snippet. #2394

Merged
merged 3 commits into from
Jul 8, 2018
Merged
Show file tree
Hide file tree
Changes from all 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
48 changes: 32 additions & 16 deletions browser/src/Services/Snippets/SnippetSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* Manages snippet integration
*/

import * as detectIndent from "detect-indent"
import * as types from "vscode-languageserver-types"

import * as Oni from "oni-api"
Expand Down Expand Up @@ -75,6 +76,19 @@ export const makeSnippetConsistentWithExistingWhitespace = (
return snippet.split("\t").join(info.indent)
}

export const makeSnippetIndentationConsistent = (snippet: string, info: BufferIndentationInfo) => {
return snippet
.split("\n")
.map((line, index) => {
if (index === 0) {
return line
} else {
return info.indent + line
}
})
.join("\n")
}

export class SnippetSession {
private _buffer: IBuffer
private _snippet: OniSnippet
Expand Down Expand Up @@ -120,22 +134,6 @@ export class SnippetSession {
public async start(): Promise<void> {
this._buffer = this._editor.activeBuffer as IBuffer

const whitespaceSettings = await this._buffer.detectIndentation()
const normalizedSnippet = makeSnippetConsistentWithExistingWhitespace(
this._snippetString,
whitespaceSettings,
)
this._snippet = new OniSnippet(normalizedSnippet, new SnippetVariableResolver(this._buffer))

// If there are no placeholders, add an implicit one at the end
if (this._snippet.getPlaceholders().length === 0) {
this._snippet = new OniSnippet(
// tslint:disable-next-line
normalizedSnippet + "${0}",
new SnippetVariableResolver(this._buffer),
)
}

const cursorPosition = await this._buffer.getCursorPosition()
const [currentLine] = await this._buffer.getLines(
cursorPosition.line,
Expand All @@ -145,15 +143,33 @@ export class SnippetSession {
this._position = cursorPosition

const [prefix, suffix] = splitLineAtPosition(currentLine, cursorPosition.character)
const currentIndent = detectIndent(currentLine)

this._prefix = prefix
this._suffix = suffix

const whitespaceSettings = await this._buffer.detectIndentation()
const normalizedSnippet = makeSnippetConsistentWithExistingWhitespace(
this._snippetString,
whitespaceSettings,
)
const indentedSnippet = makeSnippetIndentationConsistent(normalizedSnippet, currentIndent)
this._snippet = new OniSnippet(indentedSnippet, new SnippetVariableResolver(this._buffer))

const snippetLines = this._snippet.getLines()
const lastIndex = snippetLines.length - 1
snippetLines[0] = this._prefix + snippetLines[0]
snippetLines[lastIndex] = snippetLines[lastIndex] + this._suffix

// If there are no placeholders, add an implicit one at the end
if (this._snippet.getPlaceholders().length === 0) {
this._snippet = new OniSnippet(
// tslint:disable-next-line
indentedSnippet + "${0}",
new SnippetVariableResolver(this._buffer),
)
}

await this._buffer.setLines(cursorPosition.line, cursorPosition.line + 1, snippetLines)

const placeholders = this._snippet.getPlaceholders()
Expand Down
52 changes: 50 additions & 2 deletions browser/test/Services/Snippets/SnippetSessionTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ describe("SnippetSession", () => {
assert.strictEqual(firstLine, "somefooline")
})

it("matches existing whitespace - 2 spaces", async () => {
it("matches existing whitespace for first line - 2 spaces", async () => {
snippetSession = new SnippetSession(mockEditor as any, "\t\tfoo")

const indentationInfo = {
Expand All @@ -66,7 +66,7 @@ describe("SnippetSession", () => {
assert.strictEqual(firstLine, " foo")
})

it("matches existing whitespace - tabs", async () => {
it("matches existing whitespace for first line - tabs", async () => {
snippetSession = new SnippetSession(mockEditor as any, "\t\tfoo")

const indentationInfo = {
Expand Down Expand Up @@ -119,6 +119,54 @@ describe("SnippetSession", () => {
assert.strictEqual(secondLine, "barline")
})

it("matches existing whitespace for whole snippet - 2 spaces", async () => {
snippetSession = new SnippetSession(mockEditor as any, "for {\n\tthing\n}")

const indentationInfo = {
type: "space",
amount: 2,
indent: " ",
}

mockBuffer.setWhitespace(indentationInfo as any)

// Add a line, and move cursor to line
mockBuffer.setLinesSync([" "])
mockBuffer.setCursorPosition(0, 2)

await snippetSession.start()

const [firstLine, secondLine, thirdLine] = await mockBuffer.getLines(0, 3)

assert.strictEqual(firstLine, " for {")
assert.strictEqual(secondLine, " thing")
assert.strictEqual(thirdLine, " }")
})

it("matches existing whitespace for whole snippet - tabs", async () => {
snippetSession = new SnippetSession(mockEditor as any, "for {\n\tthing\n}")

const indentationInfo = {
type: "tab",
amount: 0,
indent: "\t",
}

mockBuffer.setWhitespace(indentationInfo as any)

// Add a line, and move cursor to line
mockBuffer.setLinesSync(["\t"])
mockBuffer.setCursorPosition(0, 1)

await snippetSession.start()

const [firstLine, secondLine, thirdLine] = await mockBuffer.getLines(0, 3)

assert.strictEqual(firstLine, "\tfor {")
Copy link
Member

Choose a reason for hiding this comment

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

Nice! Thanks for adding these tests! 💯

assert.strictEqual(secondLine, "\t\tthing")
assert.strictEqual(thirdLine, "\t}")
})

it("highlights first placeholder", async () => {
snippetSession = new SnippetSession(mockEditor as any, "${0:test}")

Expand Down