Skip to content

Instantly share code, notes, and snippets.

@song940
Created December 13, 2023 16:45
Show Gist options
  • Save song940/e7d0407ca05c7b621401ad7ded3182ae to your computer and use it in GitHub Desktop.
Save song940/e7d0407ca05c7b621401ad7ded3182ae to your computer and use it in GitHub Desktop.
package main
import (
"bufio"
"fmt"
"io"
"log"
"os"
"strings"
)
// Items is an interface that represents either a Block or a Directive.
type Items interface {
isItem() bool
Type() string
}
// Block represents a block in the Nginx configuration.
type Block struct {
Name string
Items []Items
}
func (b Block) isItem() bool {
return true
}
func (b Block) Type() string {
return "block"
}
// Directive represents a directive in the Nginx configuration.
type Directive struct {
Name string
Value string
}
func (d Directive) isItem() bool {
return true
}
func (d Directive) Type() string {
return "directive"
}
func parseNginxConfig(reader io.Reader) (stack []Items) {
scanner := bufio.NewScanner(reader)
var currentBlock *Block
var stackPointer []Items
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if len(line) == 0 || line[0] == '#' {
continue
}
if strings.HasSuffix(line, "{") {
blockName := strings.TrimSuffix(line, "{")
newBlock := &Block{Name: blockName}
if currentBlock != nil {
currentBlock.Items = append(currentBlock.Items, newBlock)
} else {
stack = append(stack, newBlock)
}
stackPointer = append(stackPointer, newBlock)
currentBlock = newBlock
} else if strings.HasPrefix(line, "}") {
if len(stackPointer) > 1 {
stackPointer = stackPointer[:len(stackPointer)-1]
currentBlock = stackPointer[len(stackPointer)-1].(*Block)
} else {
currentBlock = nil
}
} else {
parts := strings.SplitN(line, " ", 2)
if len(parts) == 2 {
name := strings.TrimSpace(parts[0])
value := strings.TrimSpace(parts[1])
directive := &Directive{Name: name, Value: value}
if currentBlock != nil {
currentBlock.Items = append(currentBlock.Items, directive)
} else {
stack = append(stack, directive)
}
}
}
}
if err := scanner.Err(); err != nil {
fmt.Println("Error reading file:", err)
return nil
}
return stack
}
func main() {
// Replace this with your actual file path
filePath := "/Users/Lsong/Projects/confbook/nginx/sites-available/awtrix.conf"
file, err := os.Open(filePath)
if err != nil {
fmt.Println("Error opening file:", err)
return
}
defer file.Close()
nginxConfig := parseNginxConfig(file)
printNginxConfig(nginxConfig)
}
func printNginxConfig(items []Items) {
for _, item := range items {
switch v := item.(type) {
case *Block:
printBlock(v)
case *Directive:
printDirective(v)
}
}
}
func printBlock(block *Block) {
log.Println(block.Name)
printNginxConfig(block.Items)
}
func printDirective(directive *Directive) {
log.Println(directive.Name, directive.Value)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment