gfu/main.go

160 lines
4.1 KiB
Go
Raw Normal View History

/*
gfu - gophermap format utility
`gfu` manipulates gophermaps (gopher menus). It is intended to be used as part of an automation chain for managing a gopherhole using maps as the main doctype, easily allowing any document to contain links.
`gfu` can:
- Convert all lines in a file that are not valid gopher links into gopher info text (item type 'i') lines
- Deconstructing all gopher info text lines in a file back to plain text for easy editing
There are also plans to include additional features, such as:
- Adding the contents of a header file into the gophermap
- Adding the contents of a footer file into the gophermap
*Please note - Many servers already support includes, so the above may not be needed. If you are interested in this feature, you may want to check your server documentation first.*
*
Documentation
For information on using `gfu`, see the help information:
gfu --help
Information on building, downloading and installing `gfu` can be found at:
https://tildegit.org/sloum/gfu
Further information on gfu can be found at the `gfu` homepage:
https://rawtext.club/~sloum/gfu.html
*/
2019-06-24 04:52:46 +00:00
package main
import (
"bufio"
2019-06-24 04:52:46 +00:00
"bytes"
"flag"
2019-06-24 04:52:46 +00:00
"fmt"
"io"
"os"
2019-06-24 04:52:46 +00:00
"regexp"
"strings"
2019-06-24 04:52:46 +00:00
)
var re = regexp.MustCompile(`.+\t.*\t.*\t.*`)
2019-06-24 04:52:46 +00:00
func errorExit(e error, msg string) {
if e != nil {
fmt.Print(msg)
os.Exit(1)
}
}
func buildInfoText(ln string) string {
2019-06-24 04:52:46 +00:00
var out strings.Builder
out.Grow(20 + len(ln))
out.WriteString("i")
out.WriteString(ln)
2019-06-24 04:52:46 +00:00
out.WriteString("\tfalse\tnull.host\t1")
return out.String()
}
func deconstructInfoText(ln string) string {
2019-06-24 04:52:46 +00:00
text := strings.SplitN(ln, "\t", 2)
infotext := text[0]
if len(infotext) > 1 {
return infotext[1:]
2019-06-24 04:52:46 +00:00
}
return ""
2019-06-24 04:52:46 +00:00
}
func readFile(path string, build bool) bytes.Buffer {
2019-06-24 04:52:46 +00:00
file, err := os.Open(path)
errorExit(err, fmt.Sprintf("Unable to open file for reading: %s\n", path))
2019-06-24 04:52:46 +00:00
defer file.Close()
return processFile(file, build)
}
2019-06-24 04:52:46 +00:00
func processFile(file io.Reader, build bool) bytes.Buffer {
scanner := bufio.NewScanner(file)
var outFile bytes.Buffer
2019-06-24 04:52:46 +00:00
if build {
for scanner.Scan() {
l := scanner.Text()
2019-06-24 04:52:46 +00:00
if exp := re.MatchString(l); exp {
outFile.WriteString(l)
} else {
outFile.WriteString(buildInfoText(l))
2019-06-24 04:52:46 +00:00
}
outFile.WriteString("\n")
2019-06-24 04:52:46 +00:00
}
} else {
for scanner.Scan() {
l := scanner.Text()
2019-06-24 04:52:46 +00:00
if exp := re.MatchString(l); exp && l[0] == 'i' {
outFile.WriteString(deconstructInfoText(l))
2019-06-24 04:52:46 +00:00
} else {
outFile.WriteString(l)
}
outFile.WriteString("\n")
2019-06-24 04:52:46 +00:00
}
}
if err := scanner.Err(); err != nil {
errorExit(err, fmt.Sprintf("Error while reading file\n"))
}
return outFile
2019-06-24 04:52:46 +00:00
}
func writeFile(path string, outFile bytes.Buffer) {
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0)
errorExit(err, fmt.Sprintf("Unable to open file for writing: %s\n", path))
2019-06-24 04:52:46 +00:00
defer file.Close()
file.Write(outFile.Bytes())
}
func PrintHelp() {
art := `gfu - gophermap formatting utility
syntax: gfu [flags...] [filepath]
example: gfu -d ~/gopher/phlog/gophermap
default
Convert plain text lines to gophermap info text (item type 'i') lines
2019-06-24 04:52:46 +00:00
`
fmt.Fprint(os.Stderr, art)
flag.PrintDefaults()
}
func main() {
//command-line flags and responses
deconstructInfoTextLines := flag.Bool("d", false, "Deconstruct a gophermap's info text lines back to plain text")
header := flag.String("head", "", "Path to a file containing header content")
footer := flag.String("foot", "", "Path to a file containing footer content")
stdout := flag.Bool("stdout", false, "Instead of writing changes to a file, return them to stdout")
2019-06-24 04:52:46 +00:00
flag.Usage = PrintHelp
flag.Parse()
args := flag.Args()
2019-06-24 04:52:46 +00:00
if l := len(args); l != 1 {
fmt.Printf("Incorrect number of arguments. Expected 1, got %d\n", l)
2019-06-24 04:52:46 +00:00
os.Exit(1)
}
//main program
2019-06-24 04:52:46 +00:00
if *header != "" {
fmt.Println("Header functionality is not built yet, proceeding with general gophermap conversion...")
}
if *footer != "" {
fmt.Println("Footer functionality is not built yet, proceeding with general gophermap conversion...")
}
outFile := readFile(args[0], !*deconstructInfoTextLines)
if *stdout {
fmt.Print(outFile.String())
} else {
writeFile(args[0], outFile)
}
2019-06-24 04:52:46 +00:00
os.Exit(0)
}