Skip to content

Commit 56634e5

Browse files
author
Randall C. O'Reilly
committed
initial copy of code from gofmt and go/printer
1 parent ebe9aef commit 56634e5

12 files changed

+4504
-2
lines changed

README.md

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
1-
# gotopy
2-
Go to Python converter -- translates Go code into Python code
1+
# GoToPy
2+
3+
GoToPy is a Go to Python converter -- translates Go code into Python code.
4+
5+
It is based on the Go `gofmt` command source code and the go `printer` package, which parses Go files and writes them out according to standard go formatting.
6+
7+
We have modified the `printer` code in the `pyprint` package to instead print out Python code.
8+

diff/diff.go

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright 2019 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// Package diff implements a Diff function that compare two inputs
6+
// using the 'diff' tool.
7+
package diff
8+
9+
import (
10+
"io/ioutil"
11+
"os"
12+
"os/exec"
13+
"runtime"
14+
)
15+
16+
// Returns diff of two arrays of bytes in diff tool format.
17+
func Diff(prefix string, b1, b2 []byte) ([]byte, error) {
18+
f1, err := writeTempFile(prefix, b1)
19+
if err != nil {
20+
return nil, err
21+
}
22+
defer os.Remove(f1)
23+
24+
f2, err := writeTempFile(prefix, b2)
25+
if err != nil {
26+
return nil, err
27+
}
28+
defer os.Remove(f2)
29+
30+
cmd := "diff"
31+
if runtime.GOOS == "plan9" {
32+
cmd = "/bin/ape/diff"
33+
}
34+
35+
data, err := exec.Command(cmd, "-u", f1, f2).CombinedOutput()
36+
if len(data) > 0 {
37+
// diff exits with a non-zero status when the files don't match.
38+
// Ignore that failure as long as we get output.
39+
err = nil
40+
}
41+
return data, err
42+
}
43+
44+
func writeTempFile(prefix string, data []byte) (string, error) {
45+
file, err := ioutil.TempFile("", prefix)
46+
if err != nil {
47+
return "", err
48+
}
49+
_, err = file.Write(data)
50+
if err1 := file.Close(); err == nil {
51+
err = err1
52+
}
53+
if err != nil {
54+
os.Remove(file.Name())
55+
return "", err
56+
}
57+
return file.Name(), nil
58+
}

format.go

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// Copyright 2020 The Go-Python Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// This is based on gofmt source code:
6+
7+
// Copyright 2015 The Go Authors. All rights reserved.
8+
// Use of this source code is governed by a BSD-style
9+
// license that can be found in the LICENSE file.
10+
11+
package main
12+
13+
import (
14+
"bytes"
15+
"go/ast"
16+
"go/token"
17+
18+
"github.com/goki/gotopy/pyprint"
19+
)
20+
21+
// format formats the given package file originally obtained from src
22+
// and adjusts the result based on the original source via sourceAdj
23+
// and indentAdj.
24+
func format(
25+
fset *token.FileSet,
26+
file *ast.File,
27+
sourceAdj func(src []byte, indent int) []byte,
28+
indentAdj int,
29+
src []byte,
30+
cfg pyprint.Config,
31+
) ([]byte, error) {
32+
if sourceAdj == nil {
33+
// Complete source file.
34+
var buf bytes.Buffer
35+
err := cfg.Fprint(&buf, fset, file)
36+
if err != nil {
37+
return nil, err
38+
}
39+
return buf.Bytes(), nil
40+
}
41+
42+
// Partial source file.
43+
// Determine and prepend leading space.
44+
i, j := 0, 0
45+
for j < len(src) && isSpace(src[j]) {
46+
if src[j] == '\n' {
47+
i = j + 1 // byte offset of last line in leading space
48+
}
49+
j++
50+
}
51+
var res []byte
52+
res = append(res, src[:i]...)
53+
54+
// Determine and prepend indentation of first code line.
55+
// Spaces are ignored unless there are no tabs,
56+
// in which case spaces count as one tab.
57+
indent := 0
58+
hasSpace := false
59+
for _, b := range src[i:j] {
60+
switch b {
61+
case ' ':
62+
hasSpace = true
63+
case '\t':
64+
indent++
65+
}
66+
}
67+
if indent == 0 && hasSpace {
68+
indent = 1
69+
}
70+
for i := 0; i < indent; i++ {
71+
res = append(res, '\t')
72+
}
73+
74+
// Format the source.
75+
// Write it without any leading and trailing space.
76+
cfg.Indent = indent + indentAdj
77+
var buf bytes.Buffer
78+
err := cfg.Fprint(&buf, fset, file)
79+
if err != nil {
80+
return nil, err
81+
}
82+
out := sourceAdj(buf.Bytes(), cfg.Indent)
83+
84+
// If the adjusted output is empty, the source
85+
// was empty but (possibly) for white space.
86+
// The result is the incoming source.
87+
if len(out) == 0 {
88+
return src, nil
89+
}
90+
91+
// Otherwise, append output to leading space.
92+
res = append(res, out...)
93+
94+
// Determine and append trailing space.
95+
i = len(src)
96+
for i > 0 && isSpace(src[i-1]) {
97+
i--
98+
}
99+
return append(res, src[i:]...), nil
100+
}
101+
102+
// isSpace reports whether the byte is a space character.
103+
// isSpace defines a space as being among the following bytes: ' ', '\t', '\n' and '\r'.
104+
func isSpace(b byte) bool {
105+
return b == ' ' || b == '\t' || b == '\n' || b == '\r'
106+
}

0 commit comments

Comments
 (0)