Skip to content

Commit

Permalink
docs: Added readme
Browse files Browse the repository at this point in the history
  • Loading branch information
opaoz committed Jun 9, 2024
1 parent 46f5c52 commit 1bc56ed
Show file tree
Hide file tree
Showing 16 changed files with 275 additions and 15 deletions.
2 changes: 2 additions & 0 deletions .github/FUNDING.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ko_fi: opa_oz

36 changes: 36 additions & 0 deletions .github/workflows/build-and-push-lsp.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: "Build and push new LSP"

on:
release:
types: [ created ]

permissions:
contents: write
packages: write

jobs:
releases-matrix:
name: Release Go Binary
runs-on: ubuntu-latest
strategy:
matrix:
goos: [ linux, windows, darwin ]
goarch: [ "386", amd64, arm64 ]
exclude:
- goarch: "386"
goos: darwin
- goarch: arm64
goos: windows
steps:
- uses: actions/checkout@v4
- uses: wangyoucao577/go-release-action@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
goversion: "1.22"
goos: ${{ matrix.goos }}
goarch: ${{ matrix.goarch }}
binary_name: "pug-lsp"
ldflags: "-s -w"
extra_files: LICENSE


1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pug-lsp
.DS_Store
9 changes: 9 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.PHONY: help

help:
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

test: ## Run unit tests
@go test ./pkg/utils ./pkg/query ./pkg/html ./pkg/documents

.PHONY: test
49 changes: 47 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,48 @@
## LSP is under heavy development
# pug-lsp: Pug Language Protocol Server

An implementation of the Language Protocol Server for [Pug.js](https://pugjs.org)

## Features

`pug-lsp` aims to provide suggestions for you to edit `.pug` in your editor.

### Note

Project is under heavy development. Current functionality can be change in stable release.

### Tags suggestions

Auto suggest list of HTML5 tags.

![tags-suggestions](docs/tags-suggestions.png)

### Attributes suggestions

#### Auto suggest common attributes (such as `style`, `class`, `title`) for tags

![common-attributes](docs/common-attributes.png)

#### Auto suggest events (such as `onclick`, `onenter`) for tags

![events-attributes](docs/events-attributes.png)

#### Auto suggest tag-specific attributes (such as `href` for `a`)

![special-attributes](docs/special-attributes.png)

#### `&attributes` snippet

_Yes, it's [a real feature](https://pugjs.org/language/attributes.html#attributes) of Pug_

![attributes-shortcut](docs/attributes-shortcut.png)


## Thanks

- [zealot128/tree-sitter-pug](https://github.com/zealot128/tree-sitter-pug)


----

[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/S6S1UZ9P7)

Stay tuned! (and don't forget to press star!)
Binary file added docs/attributes-shortcut.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/common-attributes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/events-attributes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/special-attributes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/tags-suggestions.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
56 changes: 45 additions & 11 deletions pkg/documents/document-store.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ package documents

import (
"context"
"os"
"strings"

"github.com/opa-oz/go-todo/todo"
"github.com/opa-oz/pug-lsp/pkg/lsp"
"github.com/opa-oz/pug-lsp/pkg/pug"
"github.com/opa-oz/pug-lsp/pkg/query"
"github.com/opa-oz/pug-lsp/pkg/utils"
"github.com/pkg/errors"
"github.com/tliron/glsp"
protocol "github.com/tliron/glsp/protocol_3_16"
)

Expand All @@ -27,9 +28,8 @@ func NewDocumentStore(logger utils.Logger, fs utils.FileStore) *DocumentStore {
}
}

func (ds *DocumentStore) DocumentDidOpen(ctx context.Context, params protocol.DidOpenTextDocumentParams, notify glsp.NotifyFunc) (*Document, error) {
langID := params.TextDocument.LanguageID // @todo Maybe it's not "pug", need further investigation
ds.logger.Println("langID", langID)
func (ds *DocumentStore) DocumentDidOpen(ctx context.Context, params protocol.DidOpenTextDocumentParams) (*Document, error) {
langID := params.TextDocument.LanguageID

if langID != "pug" {
return nil, nil
Expand All @@ -44,10 +44,11 @@ func (ds *DocumentStore) DocumentDidOpen(ctx context.Context, params protocol.Di
tree, err := pug.GetParsedTreeFromString(ctx, params.TextDocument.Text)

doc := &Document{
URI: uri,
Path: path,
Content: &params.TextDocument.Text,
Tree: tree,
URI: uri,
Path: path,
Content: &params.TextDocument.Text,
Tree: tree,
Includes: make(map[string]*lsp.Include),
}

ds.documents[path] = doc
Expand All @@ -59,6 +60,7 @@ func (ds *DocumentStore) RefreshIncludes(ctx context.Context, doc *Document) {
includes, err := query.FindAllIncludes(doc.Tree)
if err != nil {
ds.logger.Err(err)
return
}

originalContent := *doc.Content
Expand All @@ -67,24 +69,56 @@ func (ds *DocumentStore) RefreshIncludes(ctx context.Context, doc *Document) {
uri := ds.partialToUri(original, doc)

newInclude := lsp.NewInclude(&original, &uri)
doc.Includes = append(doc.Includes, newInclude)
_, ok := doc.Includes[original]

if !ok {
doc.Includes[original] = newInclude
ds.LoadIncludedFile(ctx, newInclude)
}

}
}

func (ds *DocumentStore) LoadIncludedFile(ctx context.Context, include *lsp.Include) {
content, err := os.ReadFile(*include.Path)

if err != nil {
ds.logger.Err(err)
return
}

uri := *include.Path
if !strings.HasPrefix(*include.Path, "file:/") {
uri = "file://" + *include.Path
}
params := protocol.DidOpenTextDocumentParams{
TextDocument: protocol.TextDocumentItem{
URI: uri,
LanguageID: todo.String("Move to constant", "pug"),
Version: 1,
Text: string(content),
},
}

ds.DocumentDidOpen(ctx, params)
}

func (ds *DocumentStore) partialToUri(original string, doc *Document) string {
parentParts := strings.Split(doc.Path, "/")
parentFolder := parentParts[0 : len(parentParts)-1] // end of path is always file, remove it
includeParts := strings.Split(original, "/")
includeFilename := includeParts[len(includeParts)-1]

if !strings.Contains(includeFilename, ".pug") {
if !strings.HasSuffix(includeFilename, ".pug") {
includeFilename = includeFilename + ".pug"
}

parentFolder = append(parentFolder, includeParts[0:len(includeParts)-1]...)
parentFolder = append(parentFolder, includeFilename)

return strings.Join(parentFolder, "/")
joined := strings.Join(parentFolder, "/")

return joined

}

Expand Down
2 changes: 1 addition & 1 deletion pkg/documents/document.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type Document struct {
Path string
Tree *sitter.Tree
Content *string
Includes []*lsp.Include
Includes map[string]*lsp.Include
}

// ApplyChanges updates the content of the Document from LSP textDocument/didChange events.
Expand Down
88 changes: 88 additions & 0 deletions pkg/documents/document_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package documents_test

import (
"context"
"testing"

"github.com/opa-oz/pug-lsp/pkg/documents"
"github.com/opa-oz/pug-lsp/pkg/query"
"github.com/stretchr/testify/assert"
protocol "github.com/tliron/glsp/protocol_3_16"
)

func TestApplyChanges(t *testing.T) {
orig := `
doctype html
html
body
div
`
newContent := `
doctype html
html
body
div.my-class#my-div
p
span My awesome text
`

doc := documents.Document{}

changes := []interface{}{
protocol.TextDocumentContentChangeEventWhole{
Text: orig,
},
}

err := doc.ApplyChanges(context.TODO(), changes)
assert.NoError(t, err)
assert.Equal(t, *doc.Content, orig)
assert.NotNil(t, doc.Tree)

changes = []interface{}{
protocol.TextDocumentContentChangeEventWhole{
Text: newContent,
},
}
err = doc.ApplyChanges(context.TODO(), changes)
assert.NoError(t, err)
assert.Equal(t, *doc.Content, newContent)
assert.NotNil(t, doc.Tree)
}

func TestPositions(t *testing.T) {
orig := `
doctype html
html
body
div.my-class#my-div
p
span My awesome text
`

doc := documents.Document{}

changes := []interface{}{
protocol.TextDocumentContentChangeEventWhole{
Text: orig,
},
}

err := doc.ApplyChanges(context.TODO(), changes)
assert.NoError(t, err)
assert.Equal(t, *doc.Content, orig)
assert.NotNil(t, doc.Tree)

position := protocol.Position{
Line: 6,
Character: 25,
}

node := doc.GetAtPosition(&position)
assert.NotNil(t, node)
assert.Equal(t, node.Type(), string(query.ContentNodeType)) // we found "My awesome text"

node = doc.GetBeforeTrigger(&position)
assert.NotNil(t, node)
assert.Equal(t, node.Type(), string(query.TagNameNode)) // we found tag_name=span before "My awesome text"
}
44 changes: 44 additions & 0 deletions pkg/query/find-all-includes_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package query_test

import (
"context"
"strings"
"testing"

"github.com/opa-oz/pug-lsp/pkg/pug"
"github.com/opa-oz/pug-lsp/pkg/query"
"github.com/stretchr/testify/assert"
)

func TestAllIncludes(t *testing.T) {
content := `
include mixins/logo
include head
include footer
doctype html
html
div
`
testTree, err := pug.GetParsedTreeFromString(context.TODO(), content)

assert.NoError(t, err)
assert.NotNil(t, testTree)

includes, err := query.FindAllIncludes(testTree)

assert.NoError(t, err)
assert.Equal(t, len(*includes), 3)

var includesFiles []string

for _, strRange := range *includes {
original := strings.Trim(content[strRange.StartPos:strRange.EndPos], " ")

includesFiles = append(includesFiles, original)
}

assert.Equal(t, includesFiles, []string{
"mixins/logo", "head", "footer",
})
}
1 change: 1 addition & 0 deletions pkg/query/find-element.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const (
MixinNode NodeType = "mixin_use"
DoctypeNode NodeType = "doctype"
DoctypeNameNode NodeType = "doctype_name"
ContentNodeType NodeType = "content"
)

func FindUpwards(node *sitter.Node, nodeType NodeType, maxDepth int) *sitter.Node {
Expand Down
2 changes: 1 addition & 1 deletion pkg/server/document-did-open.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
)

func (s *Server) TextDocumentDidOpen(ctx *glsp.Context, params *protocol.DidOpenTextDocumentParams) error {
doc, err := s.documentStore.DocumentDidOpen(context.Background(), *params, ctx.Notify)
doc, err := s.documentStore.DocumentDidOpen(context.Background(), *params)

if err != nil {
return err
Expand Down

0 comments on commit 1bc56ed

Please sign in to comment.