-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ce9e38b
commit fa1cbd6
Showing
7 changed files
with
258 additions
and
37 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
package config | ||
|
||
type ConfigFlags struct { | ||
DryRun bool | ||
Check bool | ||
Check bool | ||
Verbose bool | ||
} | ||
|
||
type Config struct { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,57 +1,175 @@ | ||
package parser | ||
|
||
import ( | ||
"os" | ||
"strings" | ||
|
||
"github.com/charmbracelet/log" | ||
"github.com/mistweaverco/kulala-fmt/internal/config" | ||
"github.com/mistweaverco/kulala-fmt/internal/filewalker" | ||
) | ||
|
||
func containsBothDotEnvAndHttpClientEnvJson(filepaths []string) bool { | ||
var hasDotEnv, hasHttpClientEnvJson bool | ||
type Section struct { | ||
Comments []string | ||
Method string | ||
URL string | ||
Version string | ||
Headers []string | ||
Metadata []string | ||
Body string | ||
} | ||
|
||
for _, file := range filepaths { | ||
if strings.HasSuffix(file, ".env") { | ||
hasDotEnv = true | ||
} | ||
if strings.HasSuffix(file, "http-client.env.json") { | ||
hasHttpClientEnvJson = true | ||
} | ||
if hasDotEnv && hasHttpClientEnvJson { | ||
return true | ||
type Document struct { | ||
Variables []string | ||
Sections []Section | ||
Valid bool | ||
} | ||
|
||
func isRequestLine(line string) bool { | ||
return strings.HasPrefix(line, "GET") || strings.HasPrefix(line, "POST") || strings.HasPrefix(line, "PUT") || strings.HasPrefix(line, "DELETE") | ||
} | ||
|
||
func parseSection(section string, document *Document) Section { | ||
in_request := true | ||
in_header := false | ||
in_body := false | ||
parsedSection := Section{ | ||
Comments: []string{}, | ||
Method: "", | ||
URL: "", | ||
Version: "", | ||
Headers: []string{}, | ||
Metadata: []string{}, | ||
Body: "", | ||
} | ||
lines := strings.Split(section, "\n") | ||
for _, line := range lines { | ||
line = strings.TrimSpace(line) | ||
if line == "" { | ||
if in_request == false && in_body == false { | ||
in_header = false | ||
in_body = true | ||
} | ||
continue | ||
} else if strings.HasPrefix(line, "@") { | ||
document.Variables = append(document.Variables, line) | ||
continue | ||
} else if strings.HasPrefix(line, "# @") { | ||
parsedSection.Metadata = append(parsedSection.Metadata, line) | ||
continue | ||
} else if strings.HasPrefix(line, "#") { | ||
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] | ||
} | ||
in_request = false | ||
in_header = true | ||
continue | ||
} else if in_header { | ||
if strings.Contains(line, ":") { | ||
parsedSection.Headers = append(parsedSection.Headers, line) | ||
} | ||
} else if in_body { | ||
parsedSection.Body += line | ||
} | ||
} | ||
|
||
return false | ||
return parsedSection | ||
} | ||
|
||
func containsBothHttpAndRest(filepaths []string) bool { | ||
var hasDotEnv, hasHttpClientEnvJson bool | ||
func validateSection(section Section, filepath string, document Document) { | ||
if section.Method == "" { | ||
log.Error("Section is missing method", "file", filepath) | ||
document.Valid = false | ||
} | ||
if section.URL == "" { | ||
log.Error("Section is missing URL", "file", filepath) | ||
document.Valid = false | ||
} | ||
} | ||
|
||
for _, file := range filepaths { | ||
if strings.HasSuffix(file, ".rest") { | ||
hasDotEnv = true | ||
func documentToString(document Document) string { | ||
documentString := "" | ||
variableLength := len(document.Variables) | ||
for idx, variable := range document.Variables { | ||
documentString += variable + "\n" | ||
if idx == variableLength-1 { | ||
documentString += "\n" | ||
} | ||
if strings.HasSuffix(file, ".http") { | ||
hasHttpClientEnvJson = true | ||
} | ||
sectionLength := len(document.Sections) | ||
for idx, section := range document.Sections { | ||
for _, comment := range section.Comments { | ||
documentString += comment + "\n" | ||
} | ||
documentString += section.Method + " " + section.URL | ||
if section.Version != "" { | ||
documentString += " " + section.Version | ||
} | ||
documentString += "\n" | ||
for _, header := range section.Headers { | ||
documentString += header + "\n" | ||
} | ||
if hasDotEnv && hasHttpClientEnvJson { | ||
return true | ||
for _, metadata := range section.Metadata { | ||
documentString += metadata + "\n" | ||
} | ||
if section.Body != "" { | ||
documentString += "\n" + section.Body + "\n" | ||
} | ||
if idx != sectionLength-1 { | ||
documentString += "\n###\n\n" | ||
} | ||
} | ||
|
||
return false | ||
return documentString | ||
} | ||
|
||
func Start(flags config.ConfigFlags) { | ||
filepath_pkgs, _ := filewalker.GetFiles() | ||
for _, filepath_pkg := range filepath_pkgs { | ||
if containsBothDotEnvAndHttpClientEnvJson(filepath_pkg) { | ||
log.Warn("You have both .env and http-client.env.json files in the same directory. This is not recommended.") | ||
func parser(filepath string, flags config.ConfigFlags) { | ||
document := Document{ | ||
Valid: true, | ||
Variables: []string{}, | ||
Sections: []Section{}, | ||
} | ||
fileContents, err := os.ReadFile(filepath) | ||
if err != nil { | ||
log.Fatal("Error reading file", "error", err) | ||
} | ||
sections := strings.Split(string(fileContents), "###") | ||
for _, section := range sections { | ||
section = strings.TrimSpace(section) | ||
if section == "" { | ||
continue | ||
} | ||
parsedSection := parseSection(section, &document) | ||
document.Sections = append(document.Sections, parsedSection) | ||
validateSection(parsedSection, filepath, document) | ||
} | ||
if !document.Valid { | ||
log.Error("File is not valid, can't fix, skipping.", "file", filepath) | ||
return | ||
} | ||
fileContentsAsString := string(fileContents) | ||
documentString := documentToString(document) | ||
if !flags.Check { | ||
if fileContentsAsString != documentString { | ||
log.Warn("File is not formatted correctly, fixing now.", "file", filepath) | ||
if flags.Verbose { | ||
log.Info("Writing", filepath, documentString) | ||
} | ||
err := os.WriteFile(filepath, []byte(documentString), 0644) | ||
if err != nil { | ||
log.Fatal("Error writing file", "error", err) | ||
} | ||
} | ||
if containsBothHttpAndRest(filepath_pkg) { | ||
log.Warn("You have both .rest and .http files in the same directory. This is not recommended.") | ||
} else { | ||
if fileContentsAsString != documentString { | ||
log.Warn("File is not formatted correctly", "file", filepath) | ||
if flags.Verbose { | ||
log.Info("Expected output", filepath, documentString) | ||
} | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package parser | ||
|
||
import ( | ||
"strings" | ||
|
||
"github.com/charmbracelet/log" | ||
"github.com/mistweaverco/kulala-fmt/internal/config" | ||
"github.com/mistweaverco/kulala-fmt/internal/filewalker" | ||
) | ||
|
||
func isDotEnv(filepath string) bool { | ||
return strings.HasSuffix(filepath, ".env") | ||
} | ||
|
||
func isHttpClientEnvJson(filepath string) bool { | ||
return strings.HasSuffix(filepath, "http-client.env.json") | ||
} | ||
|
||
func Start(flags config.ConfigFlags) { | ||
filepath_pkgs, _ := filewalker.GetFiles() | ||
for _, filepath_pkg := range filepath_pkgs { | ||
dirpath := getDirectoryPath(filepath_pkg[0]) | ||
if containsBothDotEnvAndHttpClientEnvJson(filepath_pkg) { | ||
log.Warn("You have both .env and http-client.env.json files in the same directory. This is not recommended.", "directory", dirpath) | ||
} | ||
if containsBothHttpAndRest(filepath_pkg) { | ||
log.Warn("You have both .rest and .http files in the same directory. This is not recommended.", "directory", dirpath) | ||
} | ||
for _, filepath := range filepath_pkg { | ||
if isDotEnv(filepath) { | ||
continue | ||
} | ||
if isHttpClientEnvJson(filepath) { | ||
continue | ||
} | ||
parser(filepath, flags) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package parser | ||
|
||
import ( | ||
"path/filepath" | ||
"strings" | ||
) | ||
|
||
func getDirectoryPath(path string) string { | ||
return filepath.Dir(path) | ||
} | ||
|
||
func containsBothDotEnvAndHttpClientEnvJson(filepaths []string) bool { | ||
var hasDotEnv, hasHttpClientEnvJson bool | ||
|
||
for _, file := range filepaths { | ||
if strings.HasSuffix(file, ".env") { | ||
hasDotEnv = true | ||
} | ||
if strings.HasSuffix(file, "http-client.env.json") { | ||
hasHttpClientEnvJson = true | ||
} | ||
if hasDotEnv && hasHttpClientEnvJson { | ||
return true | ||
} | ||
} | ||
return false | ||
} | ||
|
||
func containsBothHttpAndRest(filepaths []string) bool { | ||
var hasDotEnv, hasHttpClientEnvJson bool | ||
|
||
for _, file := range filepaths { | ||
if strings.HasSuffix(file, ".rest") { | ||
hasDotEnv = true | ||
} | ||
if strings.HasSuffix(file, ".http") { | ||
hasHttpClientEnvJson = true | ||
} | ||
if hasDotEnv && hasHttpClientEnvJson { | ||
return true | ||
} | ||
} | ||
return false | ||
} |