Skip to content

Commit

Permalink
feat: add kulala.nvim v3 support
Browse files Browse the repository at this point in the history
  • Loading branch information
gorillamoe committed Aug 13, 2024
1 parent dd62632 commit 4d9e63e
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 25 deletions.
39 changes: 37 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,44 @@ kulala-fmt --check --verbose file1.http file2.rest http/*.http
- Checks if the file is formatted and valid
- Removes extraneous newlines
- Makes sure document variables are at the top of the file
- Lowercases all headers
- Puts all metadata right after the headers
- Lowercases all headers (when HTTP/2 or HTTP/3) else it will uppercase the first letter
- Puts all metadata right before the request line
- Ensures all comments are using `#` and not `//`
- Ensures all comments are at the top of the request

So a perfect request would look like this:

```http
@variables1=value1
# This is a comment
# This is another comment
# @someother metatag
# @name REQUEST_NAME_ONE
GET http://localhost:8080/api/v1/health HTTP/1.1
Content-Type: application/json
{
"key": "value"
}
```

or this:

```http
@variables1=value1
# This is a comment
# This is another comment
# @someother metatag
# @name REQUEST_NAME_ONE
GET http://localhost:8080/api/v1/health HTTP/2
content-type: application/json
{
"key": "value"
}
```

If run on all files it also warns when it finds both `.env` and `http-client.env.json`
files in the same directory, because that might cause unexpected behavior.
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ require (
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.17.0 // indirect
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQz
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
97 changes: 74 additions & 23 deletions internal/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,32 @@ package parser

import (
"os"
"regexp"
"strings"

"github.com/charmbracelet/log"
"github.com/mistweaverco/kulala-fmt/internal/config"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)

type Header struct {
Name string
Value string
}

type Metadata struct {
Name string
Value string
}

type Section struct {
Comments []string
Method string
URL string
Version string
Headers []string
Metadata []string
Headers []Header
Metadata []Metadata
Body string
}

Expand All @@ -24,6 +37,33 @@ type Document struct {
Valid bool
}

var caser = cases.Title(language.Und)
var metaDataRegex = regexp.MustCompile("^# @")

func parseHTTPLine(line string) (method string, url string, version string) {
method = ""
url = ""
version = ""

pattern := `^(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\s+(\S+)\s*(.*?)(HTTP/\d+\.?\d?)?$`

re := regexp.MustCompile(pattern)

matches := re.FindStringSubmatch(line)

if len(matches) > 0 {
method = matches[1]
url = matches[2]
if matches[4] != "" {
version = matches[4]
} else {
version = "HTTP/1.1" // Default to HTTP/1.1 if not provided
}
}

return method, url, version
}

func isRequestLine(line string) bool {
return strings.HasPrefix(line, "GET") || strings.HasPrefix(line, "POST") || strings.HasPrefix(line, "PUT") || strings.HasPrefix(line, "DELETE")
}
Expand All @@ -37,8 +77,8 @@ func parseSection(section string, document *Document) Section {
Method: "",
URL: "",
Version: "",
Headers: []string{},
Metadata: []string{},
Headers: []Header{},
Metadata: []Metadata{},
Body: "",
}
lines := strings.Split(section, "\n")
Expand All @@ -53,7 +93,13 @@ func parseSection(section string, document *Document) Section {
document.Variables = append(document.Variables, line)
continue
} else if strings.HasPrefix(line, "# @") {
parsedSection.Metadata = append(parsedSection.Metadata, line)
metadata := strings.Split(metaDataRegex.ReplaceAllString(line, ""), " ")
metaDataName := metadata[0]
metaDataValue := strings.Join(metadata[1:], " ")
parsedSection.Metadata = append(parsedSection.Metadata, Metadata{
Name: metaDataName,
Value: metaDataValue,
})
continue
} else if strings.HasPrefix(line, "#") || strings.HasPrefix(line, "//") {
if strings.HasPrefix(line, "//") {
Expand All @@ -64,22 +110,27 @@ func parseSection(section string, document *Document) Section {
parsedSection.Comments = append(parsedSection.Comments, line)
continue
} else if isRequestLine(line) {
splits := strings.Split(line, " ")
parsedSection.Method = splits[0]
parsedSection.URL = splits[1]
if len(splits) > 2 {
parsedSection.Version = splits[2]
}
reqMethod, reqURL, reqVersion := parseHTTPLine(line)
parsedSection.Method = reqMethod
parsedSection.URL = reqURL
parsedSection.Version = reqVersion
in_request = false
in_header = true
continue
} else if in_header {
if strings.Contains(line, ":") {
httpVersion := parsedSection.Version
line = strings.Trim(line, " ")
splits := strings.Split(line, ":")
splits[0] = strings.ToLower(splits[0])
line = strings.Join(splits, ":")
parsedSection.Headers = append(parsedSection.Headers, line)
headerName := strings.ToLower(splits[0])
headerValue := strings.Join(splits[1:], ":")
if httpVersion != "HTTP/2" && httpVersion != "HTTP/3" {
headerName = caser.String(headerName)
}
parsedSection.Headers = append(parsedSection.Headers, Header{
Name: headerName,
Value: headerValue,
})
}
} else if in_body {
parsedSection.Body += line
Expand Down Expand Up @@ -117,8 +168,14 @@ func documentToString(document Document) string {
documentString += comment + "\n"
}
for _, metadata := range section.Metadata {
if strings.HasPrefix(metadata, "# @name ") {
documentString += metadata + "\n"
if metadata.Name == "name" {
continue
}
documentString += "# @" + metadata.Name + " " + metadata.Value + "\n"
}
for _, metadata := range section.Metadata {
if metadata.Name == "name" {
documentString += "# @" + metadata.Name + " " + metadata.Value + "\n"
}
}
documentString += section.Method + " " + section.URL
Expand All @@ -127,13 +184,7 @@ func documentToString(document Document) string {
}
documentString += "\n"
for _, header := range section.Headers {
documentString += header + "\n"
}
for _, metadata := range section.Metadata {
if strings.HasPrefix(metadata, "# @name ") {
continue
}
documentString += metadata + "\n"
documentString += header.Name + ": " + header.Value + "\n"
}
if section.Body != "" {
documentString += "\n" + section.Body + "\n"
Expand Down

0 comments on commit 4d9e63e

Please sign in to comment.