Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to use GitHub Actions, go.mod, and fix for Go 1.20 #1

Merged
merged 7 commits into from
Mar 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Tests

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
build-linux:
strategy:
matrix:
go: ['1.20', '1.19']
os: [ubuntu-latest, macos-latest, windows-latest]

name: Go ${{ matrix.go }} on ${{ matrix.os }}

runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v3

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go }}

- name: Run tests
run: |
go version
go test -race ./...

- name: Test that binary builds
run: |
go build
./gosnip "fmt.Println(time.Now())"
13 changes: 0 additions & 13 deletions .travis.yml

This file was deleted.

5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# gosnip: run small snippets of Go code from the command line

[![GoDoc](https://godoc.org/github.com/benhoyt/gosnip?status.png)](https://godoc.org/github.com/benhoyt/gosnip)
[![TravisCI Build](https://travis-ci.org/benhoyt/gosnip.svg)](https://travis-ci.org/benhoyt/gosnip)
[![AppVeyor Build](https://ci.appveyor.com/api/projects/status/github/benhoyt/gosnip?branch=master&svg=true)](https://ci.appveyor.com/project/benhoyt/gosnip)
[![Documentation](https://pkg.go.dev/badge/github.com/benhoyt/gosnip)](https://pkg.go.dev/github.com/benhoyt/gosnip)
[![GitHub Actions Build](https://github.com/benhoyt/gosnip/workflows/Tests/badge.svg)](https://github.com/benhoyt/gosnip/actions/workflows/tests.yml)

Package gosnip is a tool that allows you to run small snippets of
Go code from the command line.
Expand Down
13 changes: 0 additions & 13 deletions appveyor.yml

This file was deleted.

10 changes: 10 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module github.com/benhoyt/gosnip

go 1.19

require golang.org/x/tools v0.7.0

require (
golang.org/x/mod v0.9.0 // indirect
golang.org/x/sys v0.6.0 // indirect
)
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
47 changes: 23 additions & 24 deletions gosnip.go
Original file line number Diff line number Diff line change
@@ -1,53 +1,52 @@
// Package gosnip is a tool that allows you to run small snippets of
// Go code from the command line.
//
// usage: gosnip [-d] [-i import ...] statements...
// usage: gosnip [-d] [-i import ...] statements...
//
// For simple uses, just specify one or more Go statements on the
// command line, and gosnip will roll them into a full Go program and
// run the result using "go run". Standard library imports and any
// imports needed for packages in GOPATH are added automatically
// (using the same logic as the "goimports" tool). Some examples:
//
// $ gosnip 'fmt.Println("Hello world")'
// Hello world
// $ gosnip 'fmt.Println("Hello world")'
// Hello world
//
// $ gosnip 'fmt.Println("Current time:")' 'fmt.Println(time.Now())'
// Current time:
// 2018-11-24 16:18:47.101951 -0500 EST m=+0.000419239
// $ gosnip 'fmt.Println("Current time:")' 'fmt.Println(time.Now())'
// Current time:
// 2018-11-24 16:18:47.101951 -0500 EST m=+0.000419239
//
// The -i flag allows you to specify an import explicitly, which may be
// needed to select between ambiguous stdlib imports such as
// "text/template" and "html/template" (multiple -i flags are
// allowed). For example:
//
// $ ./gosnip -i text/template 't, _ := template.New("w").Parse("{{ . }}\n")' \
// 't.Execute(os.Stdout, "<b>")'
// <b>
// $ ./gosnip -i html/template 't, _ := template.New("w").Parse("{{ . }}\n")' \
// 't.Execute(os.Stdout, "<b>")'
// &lt;b&gt;
// $ ./gosnip -i text/template 't, _ := template.New("w").Parse("{{ . }}\n")' \
// 't.Execute(os.Stdout, "<b>")'
// <b>
// $ ./gosnip -i html/template 't, _ := template.New("w").Parse("{{ . }}\n")' \
// 't.Execute(os.Stdout, "<b>")'
// &lt;b&gt;
//
// The -d flag turns on debug mode, which prints the full program on
// stderr before running it. For example:
//
// $ gosnip -d 'fmt.Println(time.Now())'
// package main
// $ gosnip -d 'fmt.Println(time.Now())'
// package main
//
// import (
// "fmt"
// "time"
// )
// import (
// "fmt"
// "time"
// )
//
// func main() {
// fmt.Println(time.Now())
// }
// 2018-11-24 16:33:56.681024 -0500 EST m=+0.000383308
// func main() {
// fmt.Println(time.Now())
// }
// 2018-11-24 16:33:56.681024 -0500 EST m=+0.000383308
//
// The gosnip command-line tool is a thin wrapper around the
// "sniplib" package. To run Go snippets in your Go programs, see the
// sniplib docs.
//
package main

import (
Expand All @@ -59,7 +58,7 @@ import (
)

const (
version = "v1.1.1"
version = "v1.2.0"
)

func main() {
Expand Down
33 changes: 11 additions & 22 deletions sniplib/sniplib.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"os"
"os/exec"
"strings"
"syscall"

importspkg "golang.org/x/tools/imports"
)
Expand Down Expand Up @@ -69,41 +68,31 @@ func Run(source string, stdin io.Reader, stdout, stderr io.Writer) error {
errBuf := &bytes.Buffer{}
cmd.Stderr = errBuf
err = cmd.Run()
if exitStatus(err) == 2 {
// "go run" exit status 2 means compile error, so filter the
// funky temp filename and extraneous "go run" comments
if err != nil {
// Ideally we'd only do this filtering on compile error, not program
// error, but it's hard to tell the difference ("go run" used to
// return exit code 2 for this, but since Go 1.20, it doesn't).
filterStderr(errBuf.Bytes(), stderr)
return err
}
_, _ = errBuf.WriteTo(stderr)
return err
}

// Return exit status from given exec error (there'll be a better way
// to do this in Go 1.12!).
func exitStatus(err error) int {
if err == nil {
return 0
}
if exitErr, ok := err.(*exec.ExitError); ok {
if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
return status.ExitStatus()
}
}
return 1
}

// Filter out extraneous output and temp file name from "go run"
// output in case of compile error. Example "go run" output:
//
// # command-line-arguments
// /var/folders/sz/thh6m7316b3gvvvmjp8qpdrm0000gp/T/gosnip_615300750.go:8:2: undefined: fmt.X
// # command-line-arguments
// /var/folders/sz/thh6m7316b3gvvvmjp8qpdrm0000gp/T/gosnip_615300750.go:8:2: undefined: fmt.X
//
// Output after filtering:
//
// 8:2: undefined: fmt.X
//
// 8:2: undefined: fmt.X
func filterStderr(data []byte, writer io.Writer) {
if !bytes.Contains(data, []byte("# command-line-arguments")) {
writer.Write(data)
return
}
lines := bytes.Split(data, []byte("\n"))
for _, line := range lines {
if bytes.HasPrefix(line, []byte("# ")) {
Expand Down
23 changes: 18 additions & 5 deletions sniplib/sniplib_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"bytes"
"fmt"
"os"
"regexp"
"strings"
"testing"

Expand Down Expand Up @@ -149,8 +150,8 @@ func main() {
}
`,
"",
"8:2: undefined: fmt.X\n",
"exit status 2",
"8:6: undefined: fmt.X\n",
"exit status [12]",
},
{
`package main
Expand Down Expand Up @@ -178,7 +179,7 @@ func main() {
`,
"",
"4:2: undefined: foo\n",
"exit status 2",
"exit status [12]",
},
}
for _, test := range tests {
Expand All @@ -194,14 +195,26 @@ func main() {
t.Errorf("expected stderr %q, got %q", test.stderr, errBuf.String())
}
if err != nil {
if err.Error() != test.err {
t.Errorf("expected error %q, got %q", test.err, err.Error())
if !mustMatch(test.err, err.Error()) {
t.Errorf("expected error to match %q, got %q", test.err, err.Error())
}
} else {
if test.err != "" {
t.Errorf("expected error to match %q, got no error", test.err)
}
}
})
}
}

func mustMatch(pattern, s string) bool {
matched, err := regexp.MatchString(pattern, s)
if err != nil {
panic(err)
}
return matched
}

func ExampleToProgram() {
statements := []string{`fmt.Println("Hello world")`}
source, err := sniplib.ToProgram(statements, nil)
Expand Down