Author: LakeFox
Email: [email protected]
Date: Sun, 20 Apr 2025 21:14:43 -0600
tagc/main.go
Delete
Commits
Diff
package tagc

import (
	"bufio"
	"fmt"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

var (
	commentRegexps      []*regexp.Regexp
	sectionRegexps      []*regexp.Regexp
	continuationRegexps []*regexp.Regexp
)

// !MAN: Node Style getter/setter
// Option 1: (2 args) .Style("background","yellow") -> "" -- Sets the inline value of background
// Option 2: (1 args) .Style("background") -> "" -- Gets the inline value of background
// Option 3: (0 args) .Style("background") -> "" -- Returns all inline styles as a string
// [!DEVMAN]Note: Contains all user inputed styles, all inline styles over ride stylesheet styles
func init() {
	commentPatterns := []string{
		`^\s*//\s*!(\w+(?:,\w+)*):\s*(.*)$`, `^\s*# !(\w+):\s*(.*)$`, `^\s*; !(\w+):\s*(.*)$`, `^\s*% !(\w+):\s*(.*)$`,
		`^\s*-- !(\w+):\s*(.*)$`, `^\s*/\* !(\w+):\s*(.*)\*/`, `^\s*`,
	}

	sectionPatterns := []string{
		`^\s*//\s*(?:\+\s*(?:\[([!?\w,]+)\](\w+)|(\w+))):\s*(.*)$`, `^\s*# \+\s*(\w+):\s*(.*)$`, `^\s*; +\s*(\w+):\s*(.*)$`, `^\s*% \+\s*(\w+):\s*(.*)$`,
		`^\s*-- \+\s*(\w+):\s*(.*)$`, `^\s*/\* \+\s*(\w+):\s*(.*)\*/`, `^\s*`,
	}

	continuationPatterns := []string{
		`^\s*// \+\s*(.*)$`, `^\s*# \+\s*(.*)$`, `^\s*; \+\s*(.*)$`, `^\s*% \+\s*(.*)$`,
		`^\s*-- \+\s*(.*)$`, `^\s*/\* \+\s*(.*)\*/`, `^\s*`,
	}

	for i := range commentPatterns {
		commentRegexps = append(commentRegexps, regexp.MustCompile(commentPatterns[i]))
		sectionRegexps = append(sectionRegexps, regexp.MustCompile(sectionPatterns[i]))
		continuationRegexps = append(continuationRegexps, regexp.MustCompile(continuationPatterns[i]))
	}
}

type Comment struct {
	Tags   []string `json:"tags,omitempty" xml:"tags>tag,omitempty" text:"Tags,omitempty"`
	File   string   `json:"file,omitempty" xml:"file,omitempty" text:"Path,omitempty"`
	Line   int      `json:"line,omitempty" xml:"line,omitempty" text:"Line,omitempty"`
	Length int      `json:"length,omitempty" xml:"length,omitempty" text:"Length,omitempty"`
	Data   []string `json:"data,omitempty" xml:"data>item,omitempty" text:"Body,omitempty"`
}

func fileParser(path string) []Comment {

	file, err := os.Open(path)
	if err != nil {
		fmt.Println("Error opening file:", path, err)
		return []Comment{}
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	lines := []string{}
	for scanner.Scan() {
		lines = append(lines, scanner.Text())
	}
	return parse(path, lines)
}

func parse(path string, lines []string) []Comment {
	comments := []Comment{}

	var currentComment *Comment
	for lineNumber, line := range lines {
		for i := range commentRegexps {
			if matches := commentRegexps[i].FindStringSubmatch(line); matches != nil {
				if currentComment != nil {
					comments = append(comments, *currentComment)
				}

				currentComment = &Comment{
					File:   path,
					Line:   lineNumber + 1,
					Length: 1,
					Tags:   strings.Split(strings.TrimSpace(matches[1]), ","),
					Data:   []string{strings.TrimSpace(matches[2])},
				}
				break
			} else if matches := sectionRegexps[i].FindStringSubmatch(line); matches != nil {
				if currentComment != nil {
					label := matches[2]
					if label == "" {
						label = matches[3]
					}
					if label == "" {
						label = "[" + matches[1] + "]" + matches[2]
					}
					// this is sjda test
					currentComment.Tags = append(currentComment.Tags, label)
					currentComment.Data = append(currentComment.Data, matches[4])
					currentComment.Length += 1
				}
				break
			} else if matches := continuationRegexps[i].FindStringSubmatch(line); matches != nil {
				if currentComment != nil {
					currentComment.Data[len(currentComment.Data)-1] += "\n" + matches[1]
					currentComment.Length += 1
				}
				break
			} else if currentComment != nil {
				comments = append(comments, *currentComment)
				currentComment = nil
			}

		}

	}

	return comments
}

func loadPaths(root string) ([]string, error) {
	paths := []string{}
	err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}

		if strings.Contains(path, ".git") {
			return nil
		}

		if !info.IsDir() {
			paths = append(paths, path)
		}
		return nil
	})
	return paths, err
}

func Read(path string, handle func (interface{})) (error) {

	file, err := os.Open(path)
	if err != nil {
		return err
	}

	fileInfo, err := file.Stat()
	if err != nil {
		return err
	}

	paths := []string{}
	if fileInfo.IsDir() {
		paths, err = loadPaths(path)

		if err != nil {
			return err
		}
	} else {
		paths = append(paths, path)
	}

	for _, v := range paths {
		p := fileParser(v)
		for _, c := range p {
			handle(c)
		}
	}

	return nil
}