Author: LakeFox
Email: [email protected]
Date: Tue, 15 Apr 2025 15:21:35 -0600
main.go
Changes
Commits
Diff
diff --git a/main.go b/main.go
index 490e27c..3b9b9f0 100644
--- a/main.go
+++ b/main.go
@@ -4 +3,0 @@ import (
-	"bytes"
@@ -7 +5,0 @@ import (
-	"logc/flagtype"
@@ -9,0 +8 @@ import (
+	"logc/parser"
@@ -11,2 +9,0 @@ import (
-	"logc/tagc"
-	"net/http"
@@ -14 +11 @@ import (
-	"path/filepath"
+	"os/exec"
@@ -16 +12,0 @@ import (
-	"text/template"
@@ -19,11 +15,7 @@ import (
-// !NOTE: Contact the author at [email protected]
-
-// ?qaz.sh???
-// !NOTE: The idea is source -> filter -> encode -> output
-// + ./ (directory) -> only include issues -> parse the comments -> output text to the console
-// + .git -> get the first five commits -> parse the git repo -> output as html and save the files as user/commitid/filepath
-// + take all the files in a directory -> no filter -> add a template -> save as dirname.html
-// + take directory and output as html folder structure or json or template
-
-// !FUTURE: Add things like spreadsheets, rss, and databases (ip connections too) (try to replace retool) also email output
-// + add sorting
+// !TODO: Add above and clean mode --clean also have the search function include the code
+// + I'd like to be able to --tag=devman --search=outputCSV --format=json --clean
+// + --include-ext adds the file extention maybe a --headers that logs the CSV/JSON headers
+// + --tag logs all tags --tag="DEVMAN,TODO" includes both
+// + --headers="File,Line" only includes file and line
+// + Description: might to something like this to add a custom header
+// + hello
@@ -33,18 +25,23 @@ func main() {
-	// -src mail.privateemail.com:993 -username [email protected] -password 123qweASD
-	path := flag.String("src", ".", "Source directory or file")
-	// username := flag.String("username", "", "Email login username")
-	// password := flag.String("password", "", "Email login password")
-	mode := flag.String("mode", "tagc", "Set Content mode (\"git\", \"tagc\", \"email\", \"directory\")")
-
-	var filters flagType.FlagType
-	flag.Var(&filters, "filter", `Include entrees only matching provided the RegExp (--filter tags=/ISSUE/ --filter commit.email=/(\w)(\w*)(\w)@([^\s]+)/`)
-	var removes flagType.FlagType
-	var replaces flagType.FlagType
-	flag.Var(&removes, "remove", "Remove fields from the output")
-	flag.Var(&replaces, "replace", `RegExp to replace text within a field. Example: --replace commit.email=/(\w)(\w*)(\w)@([^\s]+)/${1}*${3}@${4}/ (censors emails it git commits)`)
-	replaceFile := flag.String("replaceFile", "", "File containing replace statements")
-
-	encoding := flag.String("encoding", "text", "Output encoding (json/xml/text/template file path)")
-
-	outputPath := flag.String("output", "stdout", "Output path (must be templated when using encoding template) default stdout")
-	outputDir := flag.String("dir", ".", "Directory to write the output file to")
+	list := flag.Bool("list", false, "List all headers")
+	headers := flag.String("headers", "", "Search Headers")
+	query := flag.String("query", "", "Search Body")
+	// clean := flag.Bool("clean", false, "Remove Comments")
+	format := flag.String("format", "", "Output format (text/json/csv/html)")
+	gitBool := flag.Bool("git", false, "Enable HTML to Git")
+	template := flag.String("template", "", "Git Template")
+	theme := flag.String("theme", "dracula", "Code Highlighting Theme")
+	outputPath := flag.String("output", "./", "HTML Output Directory")
+	address := flag.String("address", ":80", "HTTP Address to listen on")
+	serve := flag.Bool("serve", false, "Start Git Server")
+
+	// Preprocess to extract the positional argument
+	var root string
+	args := os.Args[1:] // Skip the program name
+	for i, arg := range args {
+		if !strings.HasPrefix(arg, "-") {
+			root = arg
+			// Remove the positional argument so `flag.Parse` can handle the rest
+			args = append(args[:i], args[i+1:]...)
+			break
+		}
+	}
@@ -52,2 +49,3 @@ func main() {
-	address := flag.String("address", ":6753", "HTTP Address to listen on")
-	serve := flag.Bool("serve", false, "Start HTTP Server")
+	if root == "" {
+		root = "." // Default to the current directory
+	}
@@ -55 +53,2 @@ func main() {
-	flag.Parse()
+	// Parse the remaining flags
+	flag.CommandLine.Parse(args)
@@ -58,2 +57,2 @@ func main() {
-	if _, err := os.Stat(*path); os.IsNotExist(err) {
-		fmt.Println("Directory does not exist:", path)
+	if _, err := os.Stat(root); os.IsNotExist(err) {
+		fmt.Println("Directory does not exist:", root)
@@ -63,7 +62 @@ func main() {
-	// add checks for errors
-	data := []interface{}{}
-	if *mode == "tagc" {
-		r, err := tagc.Read(*path)
-		if err != nil {
-			panic(err)
-		}
+	
@@ -71,2 +64,5 @@ func main() {
-		for _, v := range r {
-			data = append(data, v)
+	if *gitBool {
+		if *serve {
+			git.ServeHTML(root, *template, *theme, *address, *outputPath, *headers, *query)
+		} else {
+			git.ConvertRepo(root, *outputPath, *theme, *template, *headers, *query)
@@ -73,0 +70,2 @@ func main() {
+		return
+	}
@@ -75,5 +73,2 @@ func main() {
-	} else if *mode == "git" {
-		r, err := git.Read(*path)
-		if err != nil {
-			panic(err)
-		}
+	comments := []parser.Comment{}
+	paths := parser.LoadPaths(root)
@@ -81,3 +76,2 @@ func main() {
-		for _, v := range r {
-			data = append(data, v)
-		}
+	for _, v := range paths {
+		comments = append(comments, parser.File(v)...)
@@ -86 +80,4 @@ func main() {
-	results := search.All(data, filters.Array(), removes.Array(), replaces.Array(), *replaceFile)
+	if *list {
+		fmt.Println(strings.Join(output.GetHeaders(comments), ","))
+		return
+	}
@@ -88,2 +85,17 @@ func main() {
-	op := filepath.Join(*outputDir, *outputPath)
-	enc := strings.ToLower(*encoding)
+	// Filter comments based on search term
+	filteredComments := search.Text(comments, *headers, *query)
+
+	// Skip TUI if `-format` flag is present
+	if *format != "" {
+		switch strings.ToLower(*format) {
+		case "json":
+			output.JSON(filteredComments)
+		case "csv":
+			output.CSV(filteredComments)
+		case "html":
+			fmt.Println(output.HTML(filteredComments))
+		default:
+			output.Text(filteredComments)
+		}
+		return
+	} else {
@@ -91,5 +103 @@ func main() {
-	var tmpl *template.Template
-	if enc != "json" || enc != "text" || enc != "xml" {
-		templatePath := filepath.Join(*path, enc)
-		tmpl, _ = template.ParseFiles(templatePath)
-	}
+		content := output.FormatText(filteredComments, 90)
@@ -97,15 +105,3 @@ func main() {
-	for _, v := range results {
-		var data string
-		if enc == "json" {
-			data = output.JSON(v)
-		} else if enc == "text" {
-			data = output.Text(v)
-		} else if enc == "xml" {
-			data = output.XML(results)
-		} else {
-			var f bytes.Buffer
-			err := tmpl.Execute(&f, v)
-			if err != nil {
-				panic(err)
-			}
-			data = f.String()
+		editor := os.Getenv("EDITOR")
+		if editor == "" {
+			editor = "less"
@@ -112,0 +109,5 @@ func main() {
+		
+		// !ISSUE: Fix this
+		// if editor == "less" {
+		// 	content = output.HighlightText(content)
+		// }
@@ -114,12 +115,3 @@ func main() {
-		if *outputPath == "stdout" {
-			fmt.Println(data)
-		} else {
-			p := output.FormatPath(op, v)
-			if _, err := os.Stat(filepath.Dir(p)); os.IsNotExist(err) {
-				os.MkdirAll(filepath.Dir(p), 0700)
-			}
-			fmt.Println(p)
-			err := os.WriteFile(p, []byte(data), 0666)
-			if err != nil {
-				panic(err)
-			}
+		tmpFile, err := os.CreateTemp("", "highlighted_text_*.txt")
+		if err != nil {
+			return
@@ -127 +119 @@ func main() {
-	}
+		defer os.Remove(tmpFile.Name()) // Clean up after use
@@ -129,3 +121,5 @@ func main() {
-	if *serve {
-		fs := http.FileServer(http.Dir(*outputDir))
-		http.Handle("/", fs)
+		// Write content to the temporary file
+		if _, err := tmpFile.WriteString(content); err != nil {
+			return
+		}
+		tmpFile.Close()
@@ -133,5 +127,12 @@ func main() {
-		fmt.Println("Listening on:" + *address)
-		fmt.Println("Serving: " + *path)
-		err := http.ListenAndServe(*address, nil)
-		if err != nil {
-			panic(err)
+		// Construct the shell command
+
+		// Execute the command in a shell
+		cmd := exec.Command(editor, tmpFile.Name())
+		cmd.Stdin = os.Stdin
+		cmd.Stdout = os.Stdout
+		cmd.Stderr = os.Stderr
+
+		// Run and handle errors
+		if err := cmd.Run(); err != nil {
+			fmt.Fprintf(os.Stderr, "Error opening editor: %v\n", err)
+			os.Exit(1)
@@ -140,2 +140,0 @@ func main() {
-
-	return
package main

import (
	"bytes"
	"flag"
	"fmt"
	"logc/flagtype"
	"logc/git"
	"logc/output"
	"logc/search"
	"logc/tagc"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	"text/template"
)

// !NOTE: Contact the author at [email protected]

// ?qaz.sh???
// !NOTE: The idea is source -> filter -> encode -> output
// + ./ (directory) -> only include issues -> parse the comments -> output text to the console
// + .git -> get the first five commits -> parse the git repo -> output as html and save the files as user/commitid/filepath
// + take all the files in a directory -> no filter -> add a template -> save as dirname.html
// + take directory and output as html folder structure or json or template

// !FUTURE: Add things like spreadsheets, rss, and databases (ip connections too) (try to replace retool) also email output
// + add sorting

func main() {

	// -src mail.privateemail.com:993 -username [email protected] -password 123qweASD
	path := flag.String("src", ".", "Source directory or file")
	// username := flag.String("username", "", "Email login username")
	// password := flag.String("password", "", "Email login password")
	mode := flag.String("mode", "tagc", "Set Content mode (\"git\", \"tagc\", \"email\", \"directory\")")

	var filters flagType.FlagType
	flag.Var(&filters, "filter", `Include entrees only matching provided the RegExp (--filter tags=/ISSUE/ --filter commit.email=/(\w)(\w*)(\w)@([^\s]+)/`)
	var removes flagType.FlagType
	var replaces flagType.FlagType
	flag.Var(&removes, "remove", "Remove fields from the output")
	flag.Var(&replaces, "replace", `RegExp to replace text within a field. Example: --replace commit.email=/(\w)(\w*)(\w)@([^\s]+)/${1}*${3}@${4}/ (censors emails it git commits)`)
	replaceFile := flag.String("replaceFile", "", "File containing replace statements")

	encoding := flag.String("encoding", "text", "Output encoding (json/xml/text/template file path)")

	outputPath := flag.String("output", "stdout", "Output path (must be templated when using encoding template) default stdout")
	outputDir := flag.String("dir", ".", "Directory to write the output file to")

	address := flag.String("address", ":6753", "HTTP Address to listen on")
	serve := flag.Bool("serve", false, "Start HTTP Server")

	flag.Parse()

	// Validate the root directory
	if _, err := os.Stat(*path); os.IsNotExist(err) {
		fmt.Println("Directory does not exist:", path)
		os.Exit(1)
	}

	// add checks for errors
	data := []interface{}{}
	if *mode == "tagc" {
		r, err := tagc.Read(*path)
		if err != nil {
			panic(err)
		}

		for _, v := range r {
			data = append(data, v)
		}

	} else if *mode == "git" {
		r, err := git.Read(*path)
		if err != nil {
			panic(err)
		}

		for _, v := range r {
			data = append(data, v)
		}
	}

	results := search.All(data, filters.Array(), removes.Array(), replaces.Array(), *replaceFile)

	op := filepath.Join(*outputDir, *outputPath)
	enc := strings.ToLower(*encoding)

	var tmpl *template.Template
	if enc != "json" || enc != "text" || enc != "xml" {
		templatePath := filepath.Join(*path, enc)
		tmpl, _ = template.ParseFiles(templatePath)
	}

	for _, v := range results {
		var data string
		if enc == "json" {
			data = output.JSON(v)
		} else if enc == "text" {
			data = output.Text(v)
		} else if enc == "xml" {
			data = output.XML(results)
		} else {
			var f bytes.Buffer
			err := tmpl.Execute(&f, v)
			if err != nil {
				panic(err)
			}
			data = f.String()
		}

		if *outputPath == "stdout" {
			fmt.Println(data)
		} else {
			p := output.FormatPath(op, v)
			if _, err := os.Stat(filepath.Dir(p)); os.IsNotExist(err) {
				os.MkdirAll(filepath.Dir(p), 0700)
			}
			fmt.Println(p)
			err := os.WriteFile(p, []byte(data), 0666)
			if err != nil {
				panic(err)
			}
		}
	}

	if *serve {
		fs := http.FileServer(http.Dir(*outputDir))
		http.Handle("/", fs)

		fmt.Println("Listening on:" + *address)
		fmt.Println("Serving: " + *path)
		err := http.ListenAndServe(*address, nil)
		if err != nil {
			panic(err)
		}
	}

	return
}