summaryrefslogtreecommitdiff
path: root/uncrust.go
diff options
context:
space:
mode:
Diffstat (limited to 'uncrust.go')
-rw-r--r--uncrust.go118
1 files changed, 118 insertions, 0 deletions
diff --git a/uncrust.go b/uncrust.go
new file mode 100644
index 0000000..a8a362e
--- /dev/null
+++ b/uncrust.go
@@ -0,0 +1,118 @@
+package main
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "log"
+ "os"
+ "os/exec"
+ "strconv"
+ "strings"
+
+ "9fans.net/go/acme"
+ "github.com/akedrou/textdiff"
+)
+
+var (
+ fl_lang = flag.String("l", "C", "Language")
+ fl_verbose = flag.Bool("v", false, "Verbosity on")
+)
+
+func main() {
+ samfile := os.Getenv("samfile")
+ id := os.Getenv("winid")
+ if "" == id {
+ log.Fatalf("no $winid set, not running in acme?")
+ }
+
+ wid, e := strconv.Atoi(id)
+ if e != nil {
+ log.Fatalf("couldn't parse $winid: %s\n", e)
+ }
+
+ win, e := acme.Open(wid, nil)
+ if e != nil {
+ log.Fatalf("couldn't open acme window id %d: %s\n", wid, e)
+ }
+
+ body, e := win.ReadAll("body")
+ if e != nil {
+ log.Fatalf("couldn't read body of window id %d: %s\n", wid, e)
+ }
+
+ args := []string{"-l", *fl_lang}
+ stderr := &bytes.Buffer{}
+ stdout := &bytes.Buffer{}
+
+ cmd := exec.Command("uncrustify", args...)
+ cmd.Stdin = bytes.NewBuffer(body)
+ cmd.Stdout = stdout
+ cmd.Stderr = stderr
+
+ if e = cmd.Run(); e != nil {
+ if _, ok := e.(*exec.ExitError); ok {
+ str := stderr.String()
+ if len(samfile) != 0 {
+ str = strings.ReplaceAll(str, "stdin, open_line is ", samfile+":")
+ }
+ log.Fatal("error: " + str)
+ }
+ log.Fatalf("error: %s\n", e)
+ return
+ }
+
+ after := stdout.String()
+ before := string(body)
+ edits := textdiff.Strings(before, after)
+ textdiff.SortEdits(edits)
+
+ // We have to calculate the rune position from the byte position.
+ rcount := 0
+ idx := 0
+ cont := false
+ for p := range before {
+ cont = false
+ for i := range edits[idx:] {
+ cont = true
+ if edits[i].Start == p {
+ edits[i].Start = rcount
+ }
+ if edits[i].End == p {
+ edits[i].End = rcount
+ idx++
+ }
+ }
+ rcount++
+ if !cont {
+ break
+ }
+ }
+
+ if len(edits) > 0 {
+ win.Write("ctl", []byte("mark"))
+ win.Write("ctl", []byte("nomark"))
+ if *fl_verbose {
+ log.Printf("Applying %d diffs:\n%s\n", len(edits), pretty(edits, samfile))
+ }
+ }
+
+ for i := len(edits) - 1; i >= 0; i-- {
+ edit := edits[i]
+
+ addr := fmt.Sprintf("#%d,#%d", edit.Start, edit.End)
+ e = win.Addr(addr)
+ if e != nil {
+ log.Fatalf("error writing to acme/%d/addr: %s\n", wid, e)
+ }
+ win.Write("data", []byte(edit.New))
+ }
+}
+
+func pretty(e []textdiff.Edit, p string) string {
+ b := &bytes.Buffer{}
+ for _, e := range e {
+ fmt.Fprintf(b, "%s:#%d,#%d\n", p, e.Start, e.End)
+ }
+ return b.String()
+}