Skip to content

Commit

Permalink
Merge pull request #16 from mistweaverco/inrequestvars_separatelogica…
Browse files Browse the repository at this point in the history
…lblocks

InRequestVars + SeparateLogicalBlocks
  • Loading branch information
gorillamoe authored Sep 18, 2024
2 parents 14bf138 + 71d6027 commit fde99db
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 27 deletions.
52 changes: 52 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,58 @@ content-type: application/json
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.

## Formatting options

You can tweak the formatter by using some flags.

### separate-logical-blocks

Logical blocks can be separated by a newline using `--separate-logical-blocks`. For example:

```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"
}
```

### in-request-vars

When using request variables (like optaining a token from a previous request)
you may assign thie to a document after the request and
don't force to put it at the top of the file.

This can be done by using `--in-request-vars`

```http
###
# @name login
POST {{loginURL}} HTTP/1.1
Accept: application/json
Content-Type: application/x-www-form-urlencoded
client_secret={{clientSecret}}&client_id={{clientId}}&grant_type=client_credentials&scope={{scope}}
###
@token = {{login.response.body.$.access_token}}
@tokentype = {{login.response.body.$.token_type}}
###
```

## Use it with conform.nvim

```lua
Expand Down
2 changes: 2 additions & 0 deletions cmd/kulalafmt/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,6 @@ func init() {
rootCmd.PersistentFlags().BoolVar(&cfg.Flags.Check, "check", false, "check")
rootCmd.PersistentFlags().BoolVar(&cfg.Flags.Verbose, "verbose", false, "verbose")
rootCmd.PersistentFlags().BoolVar(&cfg.Flags.Version, "version", false, "version")
rootCmd.PersistentFlags().BoolVar(&cfg.Flags.InRequestVars, "in-request-vars", false, "don't enforce document variables to be at top of the file")
rootCmd.PersistentFlags().BoolVar(&cfg.Flags.SeparateLogicalBlocks, "separate-logical-blocks", false, "don't enforce trimming of all blank lines")
}
2 changes: 2 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ type ConfigFlags struct {
Check bool
Verbose bool
Version bool
InRequestVars bool
SeparateLogicalBlocks bool
}

type Config struct {
Expand Down
101 changes: 74 additions & 27 deletions internal/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ type ParsedRequestBlock struct {
Metadata []Metadata
Body string
Delimiter string
Variables []string
LineNo int
UnmatchedLineCount int
}

type Document struct {
Expand Down Expand Up @@ -74,9 +77,10 @@ func isRequestLine(line string) bool {
type RequestBlock struct {
Content string
Delimiter string
LineNo int
}

func parseRequestBlock(requestBlock RequestBlock, document *Document) ParsedRequestBlock {
func parseRequestBlock(requestBlock RequestBlock, document *Document, flags config.ConfigFlags) ParsedRequestBlock {
in_request := true
in_header := false
in_body := false
Expand All @@ -89,6 +93,9 @@ func parseRequestBlock(requestBlock RequestBlock, document *Document) ParsedRequ
Metadata: []Metadata{},
Body: "",
Delimiter: requestBlock.Delimiter,
Variables: []string{},
LineNo: requestBlock.LineNo,
UnmatchedLineCount: 0,
}
lines := strings.Split(requestBlock.Content, "\n")
for lineidx, line := range lines {
Expand All @@ -99,7 +106,11 @@ func parseRequestBlock(requestBlock RequestBlock, document *Document) ParsedRequ
}
continue
} else if strings.HasPrefix(line, "@") {
document.Variables = append(document.Variables, line)
if flags.InRequestVars {
parsedRequestBlock.Variables = append(parsedRequestBlock.Variables, line)
} else {
document.Variables = append(document.Variables, line)
}
continue
} else if strings.HasPrefix(line, "# @") {
metadata := strings.Split(metaDataRegex.ReplaceAllString(line, ""), " ")
Expand Down Expand Up @@ -146,23 +157,34 @@ func parseRequestBlock(requestBlock RequestBlock, document *Document) ParsedRequ
if lineidx != len(lines)-1 {
parsedRequestBlock.Body += "\n"
}
} else if strings.TrimSpace(line) != "" {
parsedRequestBlock.UnmatchedLineCount++
}
}
return parsedRequestBlock
}

func validateSection(block ParsedRequestBlock, filepath string, document *Document) {
func validateSection(block ParsedRequestBlock, filepath string, document *Document, flags config.ConfigFlags) {
if flags.InRequestVars {
if block.Method == "" && block.URL == "" && block.UnmatchedLineCount == 0 && len(block.Variables) > 0 {
return
}
}
if block.Method == "" {
log.Error("Section is missing method", "file", filepath)
log.Error("Section is missing method", "file", filepath, "line", block.LineNo)
document.Valid = false
}
if block.URL == "" {
log.Error("Section is missing URL", "file", filepath)
log.Error("Section is missing URL", "file", filepath, "line", block.LineNo)
document.Valid = false
}
if block.UnmatchedLineCount > 0 {
log.Error("Section contains unmatched lines", "file", filepath, "line", block.LineNo)
document.Valid = false
}
}

func documentToString(document Document) string {
func documentToString(document Document, flags config.ConfigFlags) string {
documentString := ""
variableLength := len(document.Variables)
for idx, variable := range document.Variables {
Expand All @@ -173,30 +195,54 @@ func documentToString(document Document) string {
}
blocksLength := len(document.Blocks)
for idx, block := range document.Blocks {
for _, comment := range block.Comments {
documentString += comment + "\n"
needsseparator := false
if len(block.Comments) > 0 {
for _, comment := range block.Comments {
documentString += comment + "\n"
}
needsseparator = flags.SeparateLogicalBlocks
}
for _, metadata := range block.Metadata {
if metadata.Name == "name" {
continue
if len(block.Variables) > 0 {
if needsseparator {
documentString += "\n"
}
documentString += "# @" + metadata.Name + " " + metadata.Value + "\n"
for _, variable := range block.Variables {
documentString += variable + "\n"
}
needsseparator = flags.SeparateLogicalBlocks
}
for _, metadata := range block.Metadata {
if metadata.Name == "name" {
if len(block.Metadata) > 0 {
if needsseparator {
documentString += "\n"
}
for _, metadata := range block.Metadata {
if metadata.Name == "name" {
continue
}
documentString += "# @" + metadata.Name + " " + metadata.Value + "\n"
}
for _, metadata := range block.Metadata {
if metadata.Name == "name" {
documentString += "# @" + metadata.Name + " " + metadata.Value + "\n"
}
}
needsseparator = flags.SeparateLogicalBlocks
}
documentString += block.Method + " " + block.URL
if block.Version != "" {
documentString += " " + block.Version
}
documentString += "\n"
for _, header := range block.Headers {
documentString += header.Name + ": " + header.Value + "\n"
}
if block.Body != "" {
documentString += "\n" + block.Body + "\n"
if block.Method != "" {
if needsseparator {
documentString += "\n"
}
documentString += block.Method + " " + block.URL
if block.Version != "" {
documentString += " " + block.Version
}
documentString += "\n"
for _, header := range block.Headers {
documentString += header.Name + ": " + header.Value + "\n"
}
if block.Body != "" {
documentString += "\n" + block.Body + "\n"
}
}
if idx != blocksLength-1 {
documentString += "\n"+block.Delimiter+"\n\n"
Expand Down Expand Up @@ -230,6 +276,7 @@ func parser(filepath string, flags config.ConfigFlags) {
requestBlocks = append(requestBlocks, RequestBlock{
Content: strings.TrimSpace(fileContents[start:match[0]]),
Delimiter: delimiters[i],
LineNo: strings.Count(fileContents[:start], "\n"),
})
start = match[1]
}
Expand All @@ -242,15 +289,15 @@ func parser(filepath string, flags config.ConfigFlags) {
if requestBlock.Content == "" {
continue
}
parsedBlock := parseRequestBlock(requestBlock, &document)
parsedBlock := parseRequestBlock(requestBlock, &document, flags)
document.Blocks = append(document.Blocks, parsedBlock)
validateSection(parsedBlock, filepath, &document)
validateSection(parsedBlock, filepath, &document, flags)
}
if !document.Valid {
log.Error("File is not valid, can't fix, skipping.", "file", filepath)
return
}
documentString := documentToString(document)
documentString := documentToString(document, flags)
if !flags.Check {
if fileContents != documentString {
log.Warn("File is not formatted correctly, fixing now.", "file", filepath)
Expand Down

0 comments on commit fde99db

Please sign in to comment.