Skip to content

Commit

Permalink
automatic insertion of endif, endtempl, etc.
Browse files Browse the repository at this point in the history
  • Loading branch information
a-h committed May 16, 2021
1 parent 9bec583 commit a460c07
Showing 1 changed file with 99 additions and 53 deletions.
152 changes: 99 additions & 53 deletions cmd/lspcmd/changes.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ func newDocumentContents(logger *zap.Logger) *documentContents {
log: logger,
editors: []documentEditor{
autoInsertClosingTag,
autoInsertExpressionClose,
},
}
}
Expand Down Expand Up @@ -70,59 +71,6 @@ func (fc *documentContents) Apply(uri string, changes []lsp.TextDocumentContentC
return
}

type insertPosition int

const (
insertBefore insertPosition = iota
insertAfter
)

func createWorkspaceApplyEditInsert(documentURI, text string, at lsp.Position, position insertPosition) toClientRequest {
textRange := lsp.Range{
Start: at,
End: at,
}
if position == insertAfter {
textRange.Start.Character++
textRange.End.Character += len(text) + 1
}
return toClientRequest{
Method: "workspace/applyEdit",
Notif: false,
Params: applyWorkspaceEditParams{
Label: "templ close tag",
Edit: lsp.WorkspaceEdit{
Changes: map[string][]lsp.TextEdit{
documentURI: {
{
Range: textRange,
NewText: text,
},
},
},
},
},
}
}

func autoInsertClosingTag(uri, prefix string, change lsp.TextDocumentContentChangeEvent) (requests []toClientRequest) {
if change.Text == "" {
// It's a deletion.
return
}
// Check the last couple of bytes for "{%= " and "{% ".
last := 4
if last > len(prefix) {
last = len(prefix)
}
upToCaret := prefix[len(prefix)-last:] + change.Text
if shouldInsert := strings.HasSuffix(upToCaret, "{% ") || strings.HasSuffix(upToCaret, "{%= "); !shouldInsert {
return
}
requests = append(requests, createWorkspaceApplyEditInsert(uri, " %}\n", change.Range.End, insertAfter))
return
}

// Contents below adapted from https://github.com/sourcegraph/go-langserver/blob/4b49d01c8a692968252730d45980091dcec7752e/langserver/fs.go#L141
// It implements the ability to react to changes on document edits.
// MIT licensed.
Expand Down Expand Up @@ -196,3 +144,101 @@ func offsetForPosition(contents []byte, p lsp.Position) (offset int, valid bool,
}
return 0, false, fmt.Sprintf("file only has %d lines", line+1)
}

// end of content from SourceGraph.

// LSP text edit features for automatically inserting values.

// When you type "{% ", " %}" is inserted afterwards.
// When you type "{%= ", " %}" is inserted afterwards.
// When you type "{%! ", " %}" is inserted afterwards.
func autoInsertExpressionClose(uri, prefix string, change lsp.TextDocumentContentChangeEvent) (requests []toClientRequest) {
if change.Text == "" {
// It's a deletion.
return
}
// Check the last couple of bytes for "{%= ", "{% " and "{%! ".
last := 4
if last > len(prefix) {
last = len(prefix)
}
upToCaret := prefix[len(prefix)-last:] + change.Text
if shouldInsert := strings.HasSuffix(upToCaret, "{% ") || strings.HasSuffix(upToCaret, "{%= ") || strings.HasSuffix(upToCaret, "{%! "); !shouldInsert {
return
}
requests = append(requests, createWorkspaceApplyEditInsert(uri, " %}\n", change.Range.End, insertAfter))
return
}

// When you type "{% templ ", "{% endtempl %}" is inserted on the next line.
func autoInsertClosingTag(uri, prefix string, change lsp.TextDocumentContentChangeEvent) (requests []toClientRequest) {
if change.Text == "" {
// It's a deletion.
return
}
last := 10
if last > len(prefix) {
last = len(prefix)
}
upToCaret := prefix[len(prefix)-last:] + change.Text
tags := []string{
"{% templ ",
"{% if ",
"{% for ",
"{% switch ",
"{% case ",
"{% default ",
}
var insertEnd string
for i := 0; i < len(tags); i++ {
tag := tags[i]
if strings.HasSuffix(upToCaret, tag) {
insertEnd = tag[3 : len(tag)-1]
break
}
}
if insertEnd == "" {
return
}
insertAt := lsp.Position{
Line: change.Range.End.Line + 1,
Character: 0,
}
requests = append(requests, createWorkspaceApplyEditInsert(uri, "{% end"+insertEnd+" %}\n", insertAt, insertAfter))
return
}

type insertPosition int

const (
insertBefore insertPosition = iota
insertAfter
)

func createWorkspaceApplyEditInsert(documentURI, text string, at lsp.Position, position insertPosition) toClientRequest {
textRange := lsp.Range{
Start: at,
End: at,
}
if position == insertAfter {
textRange.Start.Character++
textRange.End.Character += len(text) + 1
}
return toClientRequest{
Method: "workspace/applyEdit",
Notif: false,
Params: applyWorkspaceEditParams{
Label: "templ close tag",
Edit: lsp.WorkspaceEdit{
Changes: map[string][]lsp.TextEdit{
documentURI: {
{
Range: textRange,
NewText: text,
},
},
},
},
},
}
}

0 comments on commit a460c07

Please sign in to comment.