<commit_before>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package sdb

import (
	"errors"
	"github.com/jacobsa/aws/exp/sdb/conn"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
	"sort"
	"testing"
)

func TestPut(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

func getSortedKeys(r conn.Request) []string {
	result := sort.StringSlice{}
	for key, _ := range r {
		result = append(result, key)
	}

	sort.Sort(result)
	return result
}

////////////////////////////////////////////////////////////////////////
// PutAttributes
////////////////////////////////////////////////////////////////////////

type PutTest struct {
	domainTest

	item          ItemName
	updates       []PutUpdate
	preconditions []Precondition

	err error
}

func init() { RegisterTestSuite(&PutTest{}) }

func (t *PutTest) SetUp(i *TestInfo) {
	// Call common setup code.
	t.domainTest.SetUp(i)

	// Make the request legal by default.
	t.item = "foo"
	t.updates = []PutUpdate{PutUpdate{"bar", "baz", false}}
}

func (t *PutTest) callDomain() {
	t.err = t.domain.PutAttributes(t.item, t.updates, t.preconditions)
}

func (t *PutTest) EmptyItemName() {
	t.item = ""

	// Call
	t.callDomain()

	ExpectThat(t.err, Error(HasSubstr("Invalid")))
	ExpectThat(t.err, Error(HasSubstr("item name")))
}

func (t *PutTest) InvalidItemName() {
	t.item = "taco\x80\x81\x82"

	// Call
	t.callDomain()

	ExpectThat(t.err, Error(HasSubstr("Invalid")))
	ExpectThat(t.err, Error(HasSubstr("item name")))
	ExpectThat(t.err, Error(HasSubstr(string(t.item))))
}

func (t *PutTest) ZeroUpdates() {
	t.updates = []PutUpdate{}

	// Call
	t.callDomain()

	ExpectThat(t.err, Error(HasSubstr("number")))
	ExpectThat(t.err, Error(HasSubstr("updates")))
	ExpectThat(t.err, Error(HasSubstr("0")))
}

func (t *PutTest) TooManyUpdates() {
	t.updates = make([]PutUpdate, 257)

	// Call
	t.callDomain()

	ExpectThat(t.err, Error(HasSubstr("number")))
	ExpectThat(t.err, Error(HasSubstr("updates")))
	ExpectThat(t.err, Error(HasSubstr("256")))
}

func (t *PutTest) OneAttributeNameEmpty() {
	t.updates = []PutUpdate{
		PutUpdate{Name: "foo"},
		PutUpdate{Name: "", Value: "taco"},
		PutUpdate{Name: "bar"},
	}

	// Call
	t.callDomain()

	ExpectThat(t.err, Error(HasSubstr("Invalid")))
	ExpectThat(t.err, Error(HasSubstr("attribute")))
	ExpectThat(t.err, Error(HasSubstr("name")))
	ExpectThat(t.err, Error(HasSubstr("taco")))
}

func (t *PutTest) OneAttributeNameInvalid() {
	t.updates = []PutUpdate{
		PutUpdate{Name: "foo"},
		PutUpdate{Name: "taco\x80\x81\x82"},
		PutUpdate{Name: "bar"},
	}

	// Call
	t.callDomain()

	ExpectThat(t.err, Error(HasSubstr("Invalid")))
	ExpectThat(t.err, Error(HasSubstr("attribute")))
	ExpectThat(t.err, Error(HasSubstr("name")))
	ExpectThat(t.err, Error(HasSubstr(t.updates[1].Name)))
}

func (t *PutTest) OneAttributeValueInvalid() {
	t.updates = []PutUpdate{
		PutUpdate{Name: "foo"},
		PutUpdate{Name: "bar", Value: "taco\x80\x81\x82"},
		PutUpdate{Name: "baz"},
	}

	// Call
	t.callDomain()

	ExpectThat(t.err, Error(HasSubstr("Invalid")))
	ExpectThat(t.err, Error(HasSubstr("attribute")))
	ExpectThat(t.err, Error(HasSubstr("value")))
	ExpectThat(t.err, Error(HasSubstr(t.updates[1].Value)))
}

func (t *PutTest) OnePreconditionNameEmpty() {
	t.preconditions = []Precondition{
		Precondition{Name: "foo", Exists: new(bool)},
		Precondition{Name: "", Exists: new(bool)},
		Precondition{Name: "baz", Exists: new(bool)},
	}

	// Call
	t.callDomain()

	ExpectThat(t.err, Error(HasSubstr("Invalid")))
	ExpectThat(t.err, Error(HasSubstr("attribute")))
	ExpectThat(t.err, Error(HasSubstr("name")))
}

func (t *PutTest) OnePreconditionNameInvalid() {
	t.preconditions = []Precondition{
		Precondition{Name: "foo", Exists: new(bool)},
		Precondition{Name: "taco\x80\x81\x82", Exists: new(bool)},
		Precondition{Name: "baz", Exists: new(bool)},
	}

	// Call
	t.callDomain()

	ExpectThat(t.err, Error(HasSubstr("Invalid")))
	ExpectThat(t.err, Error(HasSubstr("attribute")))
	ExpectThat(t.err, Error(HasSubstr("name")))
	ExpectThat(t.err, Error(HasSubstr(t.preconditions[1].Name)))
}

func (t *PutTest) OnePreconditionValueInvalid() {
	t.preconditions = []Precondition{
		Precondition{Name: "foo", Value: new(string)},
		Precondition{Name: "bar", Value: new(string)},
		Precondition{Name: "baz", Value: new(string)},
	}

	*t.preconditions[0].Value = ""
	*t.preconditions[1].Value = "taco\x80\x81\x82"
	*t.preconditions[2].Value = "qux"

	// Call
	t.callDomain()

	ExpectThat(t.err, Error(HasSubstr("Invalid")))
	ExpectThat(t.err, Error(HasSubstr("attribute")))
	ExpectThat(t.err, Error(HasSubstr("value")))
	ExpectThat(t.err, Error(HasSubstr(*t.preconditions[1].Value)))
}

func (t *PutTest) OnePreconditionMissingOperand() {
	t.preconditions = []Precondition{
		Precondition{Name: "foo", Exists: new(bool)},
		Precondition{Name: "bar"},
		Precondition{Name: "baz", Exists: new(bool)},
	}

	// Call
	t.callDomain()

	ExpectThat(t.err, Error(HasSubstr("Invalid")))
	ExpectThat(t.err, Error(HasSubstr("precondition")))
	ExpectThat(t.err, Error(HasSubstr("bar")))
}

func (t *PutTest) OnePreconditionHasTwoOperands() {
	t.preconditions = []Precondition{
		Precondition{Name: "foo", Exists: new(bool)},
		Precondition{Name: "bar", Exists: new(bool), Value: new(string)},
		Precondition{Name: "baz", Exists: new(bool)},
	}

	// Call
	t.callDomain()

	ExpectThat(t.err, Error(HasSubstr("Invalid")))
	ExpectThat(t.err, Error(HasSubstr("precondition")))
	ExpectThat(t.err, Error(HasSubstr("bar")))
}

func (t *PutTest) BasicParameters() {
	t.item = "some_item"
	t.updates = []PutUpdate{
		PutUpdate{Name: "foo"},
		PutUpdate{Name: "bar", Value: "taco", Replace: true},
		PutUpdate{Name: "baz", Value: "burrito"},
	}

	// Call
	t.callDomain()
	AssertNe(nil, t.c.req)

	AssertThat(
		getSortedKeys(t.c.req),
		ElementsAre(
			"Attribute.1.Name",
			"Attribute.1.Value",
			"Attribute.2.Name",
			"Attribute.2.Replace",
			"Attribute.2.Value",
			"Attribute.3.Name",
			"Attribute.3.Value",
			"DomainName",
			"ItemName",
		),
	)

	ExpectEq("foo", t.c.req["Attribute.1.Name"])
	ExpectEq("bar", t.c.req["Attribute.2.Name"])
	ExpectEq("baz", t.c.req["Attribute.3.Name"])

	ExpectEq("", t.c.req["Attribute.1.Value"])
	ExpectEq("taco", t.c.req["Attribute.2.Value"])
	ExpectEq("burrito", t.c.req["Attribute.3.Value"])

	ExpectEq("true", t.c.req["Attribute.2.Replace"])

	ExpectEq("some_item", t.c.req["ItemName"])
	ExpectEq(t.name, t.c.req["DomainName"])
}

func (t *PutTest) NoPreconditions() {
	// Call
	t.callDomain()
	AssertNe(nil, t.c.req)

	ExpectThat(getSortedKeys(t.c.req), Not(Contains(HasSubstr("Expected"))))
}

func (t *PutTest) SomePreconditions() {
	t.preconditions = []Precondition{
		Precondition{Name: "foo", Exists: new(bool)},
		Precondition{Name: "bar", Value: new(string)},
		Precondition{Name: "baz", Exists: new(bool)},
	}

	*t.preconditions[0].Exists = false
	*t.preconditions[1].Value = "taco"
	*t.preconditions[2].Exists = true

	// Call
	t.callDomain()
	AssertNe(nil, t.c.req)

	AssertThat(
		getSortedKeys(t.c.req),
		AllOf(
			Contains("Expected.1.Name"),
			Contains("Expected.2.Name"),
			Contains("Expected.3.Name"),
			Contains("Expected.1.Exists"),
			Contains("Expected.2.Value"),
			Contains("Expected.3.Exists"),
		),
	)

	ExpectEq("foo", t.c.req["Expected.1.Name"])
	ExpectEq("bar", t.c.req["Expected.2.Name"])
	ExpectEq("baz", t.c.req["Expected.3.Name"])

	ExpectEq("false", t.c.req["Expected.1.Exists"])
	ExpectEq("taco", t.c.req["Expected.2.Value"])
	ExpectEq("true", t.c.req["Expected.3.Exists"])
}

func (t *PutTest) ConnReturnsError() {
	// Conn
	t.c.err = errors.New("taco")

	// Call
	t.callDomain()

	ExpectThat(t.err, HasSubstr("SendRequest"))
	ExpectThat(t.err, HasSubstr("taco"))
}

func (t *PutTest) ConnSaysOkay() {
	ExpectEq("TODO", "")
}

////////////////////////////////////////////////////////////////////////
// BatchPutAttributes
////////////////////////////////////////////////////////////////////////

type BatchPutTest struct {
	domainTest
}

func init() { RegisterTestSuite(&BatchPutTest{}) }

func (t *BatchPutTest) DoesFoo() {
	ExpectEq("TODO", "")
}
<commit_msg>PutTest.ConnSaysOkay<commit_after>// Copyright 2012 Aaron Jacobs. All Rights Reserved.
// Author: aaronjjacobs@gmail.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package sdb

import (
	"errors"
	"github.com/jacobsa/aws/exp/sdb/conn"
	. "github.com/jacobsa/oglematchers"
	. "github.com/jacobsa/ogletest"
	"sort"
	"testing"
)

func TestPut(t *testing.T) { RunTests(t) }

////////////////////////////////////////////////////////////////////////
// Helpers
////////////////////////////////////////////////////////////////////////

func getSortedKeys(r conn.Request) []string {
	result := sort.StringSlice{}
	for key, _ := range r {
		result = append(result, key)
	}

	sort.Sort(result)
	return result
}

////////////////////////////////////////////////////////////////////////
// PutAttributes
////////////////////////////////////////////////////////////////////////

type PutTest struct {
	domainTest

	item          ItemName
	updates       []PutUpdate
	preconditions []Precondition

	err error
}

func init() { RegisterTestSuite(&PutTest{}) }

func (t *PutTest) SetUp(i *TestInfo) {
	// Call common setup code.
	t.domainTest.SetUp(i)

	// Make the request legal by default.
	t.item = "foo"
	t.updates = []PutUpdate{PutUpdate{"bar", "baz", false}}
}

func (t *PutTest) callDomain() {
	t.err = t.domain.PutAttributes(t.item, t.updates, t.preconditions)
}

func (t *PutTest) EmptyItemName() {
	t.item = ""

	// Call
	t.callDomain()

	ExpectThat(t.err, Error(HasSubstr("Invalid")))
	ExpectThat(t.err, Error(HasSubstr("item name")))
}

func (t *PutTest) InvalidItemName() {
	t.item = "taco\x80\x81\x82"

	// Call
	t.callDomain()

	ExpectThat(t.err, Error(HasSubstr("Invalid")))
	ExpectThat(t.err, Error(HasSubstr("item name")))
	ExpectThat(t.err, Error(HasSubstr(string(t.item))))
}

func (t *PutTest) ZeroUpdates() {
	t.updates = []PutUpdate{}

	// Call
	t.callDomain()

	ExpectThat(t.err, Error(HasSubstr("number")))
	ExpectThat(t.err, Error(HasSubstr("updates")))
	ExpectThat(t.err, Error(HasSubstr("0")))
}

func (t *PutTest) TooManyUpdates() {
	t.updates = make([]PutUpdate, 257)

	// Call
	t.callDomain()

	ExpectThat(t.err, Error(HasSubstr("number")))
	ExpectThat(t.err, Error(HasSubstr("updates")))
	ExpectThat(t.err, Error(HasSubstr("256")))
}

func (t *PutTest) OneAttributeNameEmpty() {
	t.updates = []PutUpdate{
		PutUpdate{Name: "foo"},
		PutUpdate{Name: "", Value: "taco"},
		PutUpdate{Name: "bar"},
	}

	// Call
	t.callDomain()

	ExpectThat(t.err, Error(HasSubstr("Invalid")))
	ExpectThat(t.err, Error(HasSubstr("attribute")))
	ExpectThat(t.err, Error(HasSubstr("name")))
	ExpectThat(t.err, Error(HasSubstr("taco")))
}

func (t *PutTest) OneAttributeNameInvalid() {
	t.updates = []PutUpdate{
		PutUpdate{Name: "foo"},
		PutUpdate{Name: "taco\x80\x81\x82"},
		PutUpdate{Name: "bar"},
	}

	// Call
	t.callDomain()

	ExpectThat(t.err, Error(HasSubstr("Invalid")))
	ExpectThat(t.err, Error(HasSubstr("attribute")))
	ExpectThat(t.err, Error(HasSubstr("name")))
	ExpectThat(t.err, Error(HasSubstr(t.updates[1].Name)))
}

func (t *PutTest) OneAttributeValueInvalid() {
	t.updates = []PutUpdate{
		PutUpdate{Name: "foo"},
		PutUpdate{Name: "bar", Value: "taco\x80\x81\x82"},
		PutUpdate{Name: "baz"},
	}

	// Call
	t.callDomain()

	ExpectThat(t.err, Error(HasSubstr("Invalid")))
	ExpectThat(t.err, Error(HasSubstr("attribute")))
	ExpectThat(t.err, Error(HasSubstr("value")))
	ExpectThat(t.err, Error(HasSubstr(t.updates[1].Value)))
}

func (t *PutTest) OnePreconditionNameEmpty() {
	t.preconditions = []Precondition{
		Precondition{Name: "foo", Exists: new(bool)},
		Precondition{Name: "", Exists: new(bool)},
		Precondition{Name: "baz", Exists: new(bool)},
	}

	// Call
	t.callDomain()

	ExpectThat(t.err, Error(HasSubstr("Invalid")))
	ExpectThat(t.err, Error(HasSubstr("attribute")))
	ExpectThat(t.err, Error(HasSubstr("name")))
}

func (t *PutTest) OnePreconditionNameInvalid() {
	t.preconditions = []Precondition{
		Precondition{Name: "foo", Exists: new(bool)},
		Precondition{Name: "taco\x80\x81\x82", Exists: new(bool)},
		Precondition{Name: "baz", Exists: new(bool)},
	}

	// Call
	t.callDomain()

	ExpectThat(t.err, Error(HasSubstr("Invalid")))
	ExpectThat(t.err, Error(HasSubstr("attribute")))
	ExpectThat(t.err, Error(HasSubstr("name")))
	ExpectThat(t.err, Error(HasSubstr(t.preconditions[1].Name)))
}

func (t *PutTest) OnePreconditionValueInvalid() {
	t.preconditions = []Precondition{
		Precondition{Name: "foo", Value: new(string)},
		Precondition{Name: "bar", Value: new(string)},
		Precondition{Name: "baz", Value: new(string)},
	}

	*t.preconditions[0].Value = ""
	*t.preconditions[1].Value = "taco\x80\x81\x82"
	*t.preconditions[2].Value = "qux"

	// Call
	t.callDomain()

	ExpectThat(t.err, Error(HasSubstr("Invalid")))
	ExpectThat(t.err, Error(HasSubstr("attribute")))
	ExpectThat(t.err, Error(HasSubstr("value")))
	ExpectThat(t.err, Error(HasSubstr(*t.preconditions[1].Value)))
}

func (t *PutTest) OnePreconditionMissingOperand() {
	t.preconditions = []Precondition{
		Precondition{Name: "foo", Exists: new(bool)},
		Precondition{Name: "bar"},
		Precondition{Name: "baz", Exists: new(bool)},
	}

	// Call
	t.callDomain()

	ExpectThat(t.err, Error(HasSubstr("Invalid")))
	ExpectThat(t.err, Error(HasSubstr("precondition")))
	ExpectThat(t.err, Error(HasSubstr("bar")))
}

func (t *PutTest) OnePreconditionHasTwoOperands() {
	t.preconditions = []Precondition{
		Precondition{Name: "foo", Exists: new(bool)},
		Precondition{Name: "bar", Exists: new(bool), Value: new(string)},
		Precondition{Name: "baz", Exists: new(bool)},
	}

	// Call
	t.callDomain()

	ExpectThat(t.err, Error(HasSubstr("Invalid")))
	ExpectThat(t.err, Error(HasSubstr("precondition")))
	ExpectThat(t.err, Error(HasSubstr("bar")))
}

func (t *PutTest) BasicParameters() {
	t.item = "some_item"
	t.updates = []PutUpdate{
		PutUpdate{Name: "foo"},
		PutUpdate{Name: "bar", Value: "taco", Replace: true},
		PutUpdate{Name: "baz", Value: "burrito"},
	}

	// Call
	t.callDomain()
	AssertNe(nil, t.c.req)

	AssertThat(
		getSortedKeys(t.c.req),
		ElementsAre(
			"Attribute.1.Name",
			"Attribute.1.Value",
			"Attribute.2.Name",
			"Attribute.2.Replace",
			"Attribute.2.Value",
			"Attribute.3.Name",
			"Attribute.3.Value",
			"DomainName",
			"ItemName",
		),
	)

	ExpectEq("foo", t.c.req["Attribute.1.Name"])
	ExpectEq("bar", t.c.req["Attribute.2.Name"])
	ExpectEq("baz", t.c.req["Attribute.3.Name"])

	ExpectEq("", t.c.req["Attribute.1.Value"])
	ExpectEq("taco", t.c.req["Attribute.2.Value"])
	ExpectEq("burrito", t.c.req["Attribute.3.Value"])

	ExpectEq("true", t.c.req["Attribute.2.Replace"])

	ExpectEq("some_item", t.c.req["ItemName"])
	ExpectEq(t.name, t.c.req["DomainName"])
}

func (t *PutTest) NoPreconditions() {
	// Call
	t.callDomain()
	AssertNe(nil, t.c.req)

	ExpectThat(getSortedKeys(t.c.req), Not(Contains(HasSubstr("Expected"))))
}

func (t *PutTest) SomePreconditions() {
	t.preconditions = []Precondition{
		Precondition{Name: "foo", Exists: new(bool)},
		Precondition{Name: "bar", Value: new(string)},
		Precondition{Name: "baz", Exists: new(bool)},
	}

	*t.preconditions[0].Exists = false
	*t.preconditions[1].Value = "taco"
	*t.preconditions[2].Exists = true

	// Call
	t.callDomain()
	AssertNe(nil, t.c.req)

	AssertThat(
		getSortedKeys(t.c.req),
		AllOf(
			Contains("Expected.1.Name"),
			Contains("Expected.2.Name"),
			Contains("Expected.3.Name"),
			Contains("Expected.1.Exists"),
			Contains("Expected.2.Value"),
			Contains("Expected.3.Exists"),
		),
	)

	ExpectEq("foo", t.c.req["Expected.1.Name"])
	ExpectEq("bar", t.c.req["Expected.2.Name"])
	ExpectEq("baz", t.c.req["Expected.3.Name"])

	ExpectEq("false", t.c.req["Expected.1.Exists"])
	ExpectEq("taco", t.c.req["Expected.2.Value"])
	ExpectEq("true", t.c.req["Expected.3.Exists"])
}

func (t *PutTest) ConnReturnsError() {
	// Conn
	t.c.err = errors.New("taco")

	// Call
	t.callDomain()

	ExpectThat(t.err, HasSubstr("SendRequest"))
	ExpectThat(t.err, HasSubstr("taco"))
}

func (t *PutTest) ConnSaysOkay() {
	// Conn
	t.c.resp = []byte{}

	// Call
	t.callDomain()

	ExpectEq(nil, t.err)
}

////////////////////////////////////////////////////////////////////////
// BatchPutAttributes
////////////////////////////////////////////////////////////////////////

type BatchPutTest struct {
	domainTest
}

func init() { RegisterTestSuite(&BatchPutTest{}) }

func (t *BatchPutTest) DoesFoo() {
	ExpectEq("TODO", "")
}
<|endoftext|>


<commit_before>//
// Copyright 2016-2018 Bryan T. Meyers <bmeyers@datadrake.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package cpan

import (
	"encoding/json"
	"fmt"
	"github.com/DataDrake/cuppa/results"
	"net/http"
	"regexp"
	"strings"
)

const (
	// APIDist is the format string for the CPAN dist API
	API = "https://fastapi.metacpan.org/v1/download_url/%s"
)

// SearchRegex is the regexp for "search.cpan.org"
var SearchRegex = regexp.MustCompile("https?://*(?:/.*cpan.org)(?:/CPAN)?/authors/id/(.*)")

// Provider is the upstream provider interface for CPAN
type Provider struct{}

// Match checks to see if this provider can handle this kind of query
func (c Provider) Match(query string) string {
	sm := SearchRegex.FindStringSubmatch(query)
	if len(sm) == 0 {
		return ""
	}
	sms := strings.Split(sm[1], "/")
	filename := sms[len(sms)-1]
	pieces := strings.Split(filename, "-")
	//pieces = pieces[0 : len(sms)-2]
	return pieces[0]
}

// Name gives the name of this provider
func (c Provider) Name() string {
	return "CPAN"
}

// Latest finds the newest release for a CPAN package
func (c Provider) Latest(name string) (r *results.Result, s results.Status) {
	// Query the API
	resp, err := http.Get(fmt.Sprintf(API, name))
	if err != nil {
		panic(err.Error())
	}
	defer resp.Body.Close()
	// Translate Status Code
	switch resp.StatusCode {
	case 200:
		s = results.OK
	case 404:
		s = results.NotFound
	default:
		s = results.Unavailable
	}

	// Fail if not OK
	if s != results.OK {
		return
	}

	dec := json.NewDecoder(resp.Body)
	rs := &Release{}
	err = dec.Decode(rs)
	if err != nil {
		panic(err.Error())
	}
	if len(rs.Error) > 0 {
		s = results.NotFound
		return
	}
	r = rs.Convert(name)
	return
}

// Releases finds all matching releases for a CPAN package
func (c Provider) Releases(name string) (rs *results.ResultSet, s results.Status) {
	r, s := c.Latest(name)
	if s != results.OK {
		return
	}
	rs = results.NewResultSet(name)
	rs.AddResult(r)
	return
}

/*
// Releases finds all matching releases for a CPAN package
func (c Provider) Releases(name string) (rs *results.ResultSet, s results.Status) {
	// Query the API
	resp, err := http.Get(fmt.Sprintf(API, name))
	if err != nil {
		panic(err.Error())
	}
	defer resp.Body.Close()
	// Translate Status Code
	switch resp.StatusCode {
	case 200:
		s = results.OK
	case 404:
		s = results.NotFound
	default:
		s = results.Unavailable
	}

	// Fail if not OK
	if s != results.OK {
		return
	}

	dec := json.NewDecoder(resp.Body)
	crs := &Releases{}
	err = dec.Decode(crs)
	if err != nil {
		panic(err.Error())
	}
	if len(crs.Releases) == 0 {
		s = results.NotFound
		return
	}
	rs = crs.Convert(name)
	return
}
*/
<commit_msg>Fix comment for golint<commit_after>//
// Copyright 2016-2018 Bryan T. Meyers <bmeyers@datadrake.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package cpan

import (
	"encoding/json"
	"fmt"
	"github.com/DataDrake/cuppa/results"
	"net/http"
	"regexp"
	"strings"
)

const (
	// API is the format string for the metacpan download_url API
	API = "https://fastapi.metacpan.org/v1/download_url/%s"
)

// SearchRegex is the regexp for "search.cpan.org"
var SearchRegex = regexp.MustCompile("https?://*(?:/.*cpan.org)(?:/CPAN)?/authors/id/(.*)")

// Provider is the upstream provider interface for CPAN
type Provider struct{}

// Match checks to see if this provider can handle this kind of query
func (c Provider) Match(query string) string {
	sm := SearchRegex.FindStringSubmatch(query)
	if len(sm) == 0 {
		return ""
	}
	sms := strings.Split(sm[1], "/")
	filename := sms[len(sms)-1]
	pieces := strings.Split(filename, "-")
	//pieces = pieces[0 : len(sms)-2]
	return pieces[0]
}

// Name gives the name of this provider
func (c Provider) Name() string {
	return "CPAN"
}

// Latest finds the newest release for a CPAN package
func (c Provider) Latest(name string) (r *results.Result, s results.Status) {
	// Query the API
	resp, err := http.Get(fmt.Sprintf(API, name))
	if err != nil {
		panic(err.Error())
	}
	defer resp.Body.Close()
	// Translate Status Code
	switch resp.StatusCode {
	case 200:
		s = results.OK
	case 404:
		s = results.NotFound
	default:
		s = results.Unavailable
	}

	// Fail if not OK
	if s != results.OK {
		return
	}

	dec := json.NewDecoder(resp.Body)
	rs := &Release{}
	err = dec.Decode(rs)
	if err != nil {
		panic(err.Error())
	}
	if len(rs.Error) > 0 {
		s = results.NotFound
		return
	}
	r = rs.Convert(name)
	return
}

// Releases finds all matching releases for a CPAN package
func (c Provider) Releases(name string) (rs *results.ResultSet, s results.Status) {
	r, s := c.Latest(name)
	if s != results.OK {
		return
	}
	rs = results.NewResultSet(name)
	rs.AddResult(r)
	return
}

/*
// Releases finds all matching releases for a CPAN package
func (c Provider) Releases(name string) (rs *results.ResultSet, s results.Status) {
	// Query the API
	resp, err := http.Get(fmt.Sprintf(API, name))
	if err != nil {
		panic(err.Error())
	}
	defer resp.Body.Close()
	// Translate Status Code
	switch resp.StatusCode {
	case 200:
		s = results.OK
	case 404:
		s = results.NotFound
	default:
		s = results.Unavailable
	}

	// Fail if not OK
	if s != results.OK {
		return
	}

	dec := json.NewDecoder(resp.Body)
	crs := &Releases{}
	err = dec.Decode(crs)
	if err != nil {
		panic(err.Error())
	}
	if len(crs.Releases) == 0 {
		s = results.NotFound
		return
	}
	rs = crs.Convert(name)
	return
}
*/
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"time"
)

var newCmd = &Command{
	UsageLine: "new [postname]",
	Short:     "new a post",
	Long: `
new a markdown format post.

after then, edit the markdown file and compile it.
`,
}

type Mapper map[string]interface{}

func init() {
	newCmd.Run = newApp
	AddCommand(newCmd)
}

func newApp(cmd *Command, args []string) {
	if len(args) == 0 {
		fmt.Fprintln(os.Stderr, "[ERRO] Argument [postname] is missing")
		os.Exit(2)
	}

	filename := "post/" + args[0] + ".md"
	_, err := os.Stat(filename)
	if err == nil || !os.IsNotExist(err) {
		fmt.Fprintf(os.Stderr, "post file %s already exist? \n", filename)
		return
	}
	err = os.MkdirAll(filepath.Dir(filename), os.ModePerm)
	if err != nil {
		fmt.Fprintf(os.Stderr, "mkdir %s error:%s\n", filename, err.Error())
		return
	}
	title := args[0]
	t := time.Now()
	y, m, _ := t.Date()
	mdata := Mapper{}
	mdata["title"] = title
	mdata["date"] = t.Format("2006-01-02 15:04:05")
	mdata["permalink"] = fmt.Sprintf("/%d/%d/%s.html", y, m, title)
	mdata["description"] = ""
	mdata["tags"] = ""
	b, err := json.MarshalIndent(mdata, "", "  ")
	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		return
	}
	err = ioutil.WriteFile(filename, b, os.ModePerm)
	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		return
	}
	fmt.Printf("new post at :%s\n", filename)
}
<commit_msg>添加默认标签<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"time"
)

var newCmd = &Command{
	UsageLine: "new [postname]",
	Short:     "new a post",
	Long: `
new a markdown format post.

after then, edit the markdown file and compile it.
`,
}

type Mapper map[string]interface{}

func init() {
	newCmd.Run = newApp
	AddCommand(newCmd)
}

func newApp(cmd *Command, args []string) {
	if len(args) == 0 {
		fmt.Fprintln(os.Stderr, "[ERRO] Argument [postname] is missing")
		os.Exit(2)
	}

	filename := "post/" + args[0] + ".md"
	_, err := os.Stat(filename)
	if err == nil || !os.IsNotExist(err) {
		fmt.Fprintf(os.Stderr, "post file %s already exist? \n", filename)
		return
	}
	err = os.MkdirAll(filepath.Dir(filename), os.ModePerm)
	if err != nil {
		fmt.Fprintf(os.Stderr, "mkdir %s error:%s\n", filename, err.Error())
		return
	}
	title := args[0]
	t := time.Now()
	y, m, _ := t.Date()
	mdata := Mapper{}
	mdata["title"] = title
	mdata["date"] = t.Format("2006-01-02 15:04:05")
	mdata["permalink"] = fmt.Sprintf("/%d/%d/%s.html", y, m, title)
	mdata["description"] = ""
	mdata["tags"] = "默认"
	b, err := json.MarshalIndent(mdata, "", "  ")
	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		return
	}
	err = ioutil.WriteFile(filename, b, os.ModePerm)
	if err != nil {
		fmt.Fprintf(os.Stderr, err.Error())
		return
	}
	fmt.Printf("new post at :%s\n", filename)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"os"
	"strings"
)

func asString(v interface{}) string {
	if v != nil {
		return fmt.Sprintf("((( %#v )))", v)
	} else {
		return ""
	}
}

func getType(t interface{}) string {
	if t == nil {
		return ""
	}

	switch t := t.(type) {
	case *ast.Ident:
		return t.Name

	case *ast.StarExpr:
		return "*" + getExpr(t.X)

	case *ast.MapType:
		return fmt.Sprintf("[%s]%s", getExpr(t.Key), getExpr(t.Value))

	case *ast.InterfaceType:
		return fmt.Sprintf("interface{%s}", getFieldList(t.Methods, true))

	default:
		return fmt.Sprintf("{{{ %#v }}}", t)
	}
}

func getExpr(expr interface{}) string {
	switch expr := expr.(type) {
	case *ast.Ident:
		return expr.Name

	case *ast.BasicLit:
		return fmt.Sprintf("%v", expr.Value)

	case *ast.UnaryExpr:
		return fmt.Sprintf("%s%s", expr.Op.String(), getExpr(expr.X))

	case *ast.BinaryExpr:
		return fmt.Sprintf("%s %s %s", getExpr(expr.X), expr.Op.String(), getExpr(expr.Y))

	case *ast.IndexExpr:
		return fmt.Sprintf("%s[%s]", getExpr(expr.X), getExpr(expr.Index))

	case *ast.SelectorExpr:
		return fmt.Sprintf("%s.%s", getExpr(expr.X), getExpr(expr.Sel))

	default:
		return fmt.Sprintf("[[[ %#v ]]]", expr)
	}
}

func getExprList(l []ast.Expr) string {
	exprs := []string{}
	for _, e := range l {
		exprs = append(exprs, getExpr(e))
	}
	return strings.Join(exprs, ", ")
}

func getFieldList(l *ast.FieldList, omitempty bool) string {
	if l != nil {
		fields := []string{}
		for _, f := range l.List {
			fields = append(fields, getNames(f.Names)+" "+getType(f.Type))
		}

		return "(" + strings.Join(fields, ", ") + ")"
	} else if omitempty {
		return ""
	} else {
		return "()"
	}
}

func getNames(v []*ast.Ident) string {
	names := []string{}

	for _, n := range v {
		names = append(names, n.Name)
	}

	return strings.Join(names, ", ")
}

type GoWalker struct {
}

func (w GoWalker) Visit(node ast.Node) (ret ast.Visitor) {
	if node == nil {
		return
	}

	switch n := node.(type) {
	case *ast.File:
		fmt.Println("//- package", n.Name)
		for _, d := range n.Decls {
			w.Visit(d)
		}

	case *ast.ValueSpec:
		fmt.Print("//-  ", getNames(n.Names))
		if n.Type != nil {
			fmt.Print(" ", getType(n.Type))
		}
		if n.Values != nil {
			fmt.Print(" = ", getExprList(n.Values))
		}
		fmt.Println("")

	case *ast.ImportSpec:
		if n.Name != nil {
			fmt.Println("//-  ", n.Name, n.Path.Value)
		} else {
			fmt.Println("//-  ", n.Path.Value)
		}

	case *ast.TypeSpec:
		fmt.Println("//-  ", n.Name, getType(n.Type))

	case *ast.GenDecl:
		fmt.Println("//-", n.Tok.String(), "{")
		for _, s := range n.Specs {
			w.Visit(s)
		}
		fmt.Println("//- }")

	case *ast.FuncDecl:
		fmt.Println("//-")
		fmt.Println("//- func", getFieldList(n.Recv, true), n.Name, getFieldList(n.Type.Params, false), getFieldList(n.Type.Results, true))
		w.Visit(n.Body)

	case *ast.BlockStmt:
		fmt.Println("//- {")
		for _, i := range n.List {
			w.Visit(i)
		}
		fmt.Println("//- }")

	case *ast.IfStmt:
		fmt.Println("//- if (", getExpr(n.Cond), ")")
		w.Visit(n.Body)
		if n.Else != nil {
			fmt.Println("//- else")
			w.Visit(n.Else)
		}

	case *ast.ReturnStmt:
		fmt.Println("//- return", getExprList(n.Results))

	case *ast.AssignStmt:
		fmt.Printf("//- %v %v %v\n", getExprList(n.Lhs), n.Tok.String(), getExprList(n.Rhs))

	default:
		fmt.Printf("/* %#v */\n", n)
		ret = w
	}

	return
}

func main() {
	args := os.Args[1:] // skip program name
	if args[0] == "--" {
		// skip - this is to fool "go run"
		args = args[1:]
	}

	fset := token.NewFileSet() // positions are relative to fset

	f, err := parser.ParseFile(fset, args[0], nil, 0)
	if err != nil {
		fmt.Println(err)
		return
	}

	var walker GoWalker
	ast.Walk(walker, f)
}
<commit_msg>Added processing of a few more statements and expression and initial support for a "Printer" interface<commit_after>package main

import (
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"os"
	"strings"
)

const (
	SP = " "
	NL = "\n"

	UP   = +1
	DOWN = -1
)

//
// Printer is the interface to be implemented to print a program
//
type Printer interface {
	updateLevel(delta int)
	printLevel(values ...string)

	printPackage(name string)
	printImport(name, path string)
	printType(name, typedef string)
	printValue(vtype, names, typedef, values string)
}

//
// GoPrinter implement the Printer interface for Go programs
//
type GoPrinter struct {
	Printer
	level int
}

func (p *GoPrinter) updateLevel(delta int) {
	p.level += delta
}

func (p *GoPrinter) indent() string {
	return strings.Repeat("  ", p.level)
}

func (p *GoPrinter) printLevel(values ...string) {
	fmt.Print(p.indent(), strings.Join(values, " "))
}

func (p *GoPrinter) printPackage(name string) {
	p.printLevel("package", name, NL)
}

func (p *GoPrinter) printImport(name, path string) {
	p.printLevel("import", name, path, NL)
}

func (p *GoPrinter) printType(name, typedef string) {
	p.printLevel("type", name, typedef, NL)
}

func (p *GoPrinter) printValue(vtype, names, typedef, value string) {
	p.printLevel(vtype, names)
	if len(typedef) > 0 {
		fmt.Print(SP, typedef)
	}
	if len(value) > 0 {
		fmt.Print(" = ", value)
	}
	fmt.Println()
}

//
// identString return the Ident name or ""
// to use when it's ok to have an empty part (and you don't want to see '<nil>')
//
func identString(i *ast.Ident) string {
	if i == nil {
		return ""
	} else {
		return i.Name
	}
}

//
// ifTrue retruns the input value if the condition is true, an empty string otherwise
//
func ifTrue(val string, cond bool) (ret string) {
	if cond {
		ret = val
	}
	return
}

func parseExpr(expr interface{}) string {
	if expr == nil {
		return ""
	}

	switch expr := expr.(type) {

	// a name
	case *ast.Ident:
		return expr.Name

		// *thing
	case *ast.StarExpr:
		return "*" + parseExpr(expr.X)

		// [len]type
	case *ast.ArrayType:
		return fmt.Sprintf("[%s]%s", parseExpr(expr.Len), parseExpr(expr.Elt))

		// [key]value
	case *ast.MapType:
		return fmt.Sprintf("[%s]%s", parseExpr(expr.Key), parseExpr(expr.Value))

		// interface{ things }
	case *ast.InterfaceType:
		return fmt.Sprintf("interface{%s}", parseFieldList(expr.Methods, true))

		// struct{ things }
	case *ast.StructType:
		return fmt.Sprintf("struct{%s}", parseFieldList(expr.Fields, true))

		// (params...) (result)
	case *ast.FuncType:
		return fmt.Sprintf("(%s) %s", parseFieldList(expr.Params, false), parseFieldList(expr.Results, true))

		// "thing", 0, true, false, nil
	case *ast.BasicLit:
		return fmt.Sprintf("%v", expr.Value)

		// type{list}
	case *ast.CompositeLit:
		return fmt.Sprintf("%s{%s}", parseExpr(expr.Type), parseExprList(expr.Elts))

		// ...type
	case *ast.Ellipsis:
		return fmt.Sprintf("...%s", parseExpr(expr.Elt))

		// -3
	case *ast.UnaryExpr:
		return fmt.Sprintf("%s%s", expr.Op.String(), parseExpr(expr.X))

		// 3 + 2
	case *ast.BinaryExpr:
		return fmt.Sprintf("%s %s %s", parseExpr(expr.X), expr.Op.String(), parseExpr(expr.Y))

		// array[index]
	case *ast.IndexExpr:
		return fmt.Sprintf("%s[%s]", parseExpr(expr.X), parseExpr(expr.Index))

		// x[low:hi:max]
	case *ast.SliceExpr:
		if expr.Max == nil {
			return fmt.Sprintf("%s[%s:%s]", parseExpr(expr.X), parseExpr(expr.Low), parseExpr(expr.High))
		} else {
			return fmt.Sprintf("%s[%s:%s:%s]", parseExpr(expr.X), parseExpr(expr.Low), parseExpr(expr.High), parseExpr(expr.Max))
		}

		// package.member
	case *ast.SelectorExpr:
		return fmt.Sprintf("%s.%s", parseExpr(expr.X), parseExpr(expr.Sel))

		// funcname(args)
	case *ast.CallExpr:
		return fmt.Sprintf("%s(%s%s)", parseExpr(expr.Fun), parseExprList(expr.Args), ifTrue("...", expr.Ellipsis > 0))

	default:
		return fmt.Sprintf("[[[ %#v ]]]", expr)
	}
}

func parseExprList(l []ast.Expr) string {
	exprs := []string{}
	for _, e := range l {
		exprs = append(exprs, parseExpr(e))
	}
	return strings.Join(exprs, ", ")
}

func parseFieldList(l *ast.FieldList, omitempty bool) string {
	if l != nil {
		fields := []string{}
		for _, f := range l.List {
			fields = append(fields, parseNames(f.Names)+" "+parseExpr(f.Type))
		}

		return "(" + strings.Join(fields, ", ") + ")"
	} else if omitempty {
		return ""
	} else {
		return "()"
	}
}

func parseNames(v []*ast.Ident) string {
	names := []string{}

	for _, n := range v {
		names = append(names, n.Name)
	}

	return strings.Join(names, ", ")
}

type GoWalker struct {
	p      Printer
	parent ast.Node
}

//
// Implement the Visitor interface for GoWalker
//
func (w GoWalker) Visit(node ast.Node) (ret ast.Visitor) {
	if node == nil {
		return
	}

	pparent := w.parent
	w.parent = node

	switch n := node.(type) {
	case *ast.File:
		w.p.printPackage(n.Name.String())
		for _, d := range n.Decls {
			w.Visit(d)
		}

	case *ast.ImportSpec:
		w.p.printImport(identString(n.Name), n.Path.Value)

	case *ast.TypeSpec:
		w.p.printType(n.Name.String(), parseExpr(n.Type))

	case *ast.ValueSpec:
		vtype := (pparent.(*ast.GenDecl)).Tok.String()
		w.p.printValue(vtype, parseNames(n.Names), parseExpr(n.Type), parseExprList(n.Values))

	case *ast.GenDecl:
		fmt.Println()
		for _, s := range n.Specs {
			w.Visit(s)
		}

	case *ast.FuncDecl:
		fmt.Println()
		w.p.printLevel("func", parseFieldList(n.Recv, true), n.Name.String(), parseFieldList(n.Type.Params, false), parseFieldList(n.Type.Results, true))
		w.Visit(n.Body)

	case *ast.BlockStmt:
		fmt.Println("{")
		w.p.updateLevel(UP)
		for _, i := range n.List {
			w.Visit(i)
		}
		w.p.updateLevel(DOWN)
		w.p.printLevel("}", NL)

	case *ast.IfStmt:
		w.p.printLevel("if (", parseExpr(n.Cond), ") ")
		w.Visit(n.Body)
		if n.Else != nil {
			w.p.printLevel("else ")
			w.Visit(n.Else)
		}

	case *ast.ReturnStmt:
		w.p.printLevel("return", parseExprList(n.Results), NL)

	case *ast.ExprStmt:
		w.p.printLevel(parseExpr(n.X), NL)

	case *ast.DeclStmt:
		w.Visit(n.Decl)

	case *ast.AssignStmt:
		w.p.printLevel(parseExprList(n.Lhs), n.Tok.String(), parseExprList(n.Rhs), NL)

	default:
		fmt.Printf("/* %#v */\n", n)
		ret = w
	}

	w.parent = pparent
	return
}

func main() {
	args := os.Args[1:] // skip program name
	if args[0] == "--" {
		// skip - this is to fool "go run"
		args = args[1:]
	}

	fset := token.NewFileSet() // positions are relative to fset

	f, err := parser.ParseFile(fset, args[0], nil, 0)
	if err != nil {
		fmt.Println(err)
		return
	}

	var printer GoPrinter
	var walker = GoWalker{&printer, nil}
	ast.Walk(walker, f)
}
<|endoftext|>


<commit_before>package gocr

import (
	"math"

	"github.com/gonum/matrix/mat64"
)

type Coordinate struct {
	row int
	col int
}

func NewCoordinate(r, c int) *Coordinate {
	return &Coordinate{
		row: r,
		col: c,
	}
}

func (c *Coordinate) N() *Coordinate {
	return &Coordinate{
		row: c.row - 1,
		col: c.col,
	}
}

func (c *Coordinate) E() *Coordinate {
	return &Coordinate{
		row: c.row,
		col: c.col + 1,
	}
}

func (c *Coordinate) S() *Coordinate {
	return &Coordinate{
		row: c.row + 1,
		col: c.col,
	}
}

func (c *Coordinate) W() *Coordinate {
	return &Coordinate{
		row: c.row,
		col: c.col - 1,
	}
}

func (c *Coordinate) NE() *Coordinate {
	return &Coordinate{
		row: c.row + 1,
		col: c.col + 1,
	}
}

func (c *Coordinate) SE() *Coordinate {
	return &Coordinate{
		row: c.row - 1,
		col: c.col + 1,
	}
}

func (c *Coordinate) SW() *Coordinate {
	return &Coordinate{
		row: c.row - 1,
		col: c.col - 1,
	}
}

func (c *Coordinate) NW() *Coordinate {
	return &Coordinate{
		row: c.row + 1,
		col: c.col - 1,
	}
}

func (c *Coordinate) IsInside(a *Area) bool {
	if a.topLeft.row == a.bottomRight.row && a.topLeft.col == a.bottomRight.col {
		return false
	}

	return c.row >= a.topLeft.row && c.col >= a.topLeft.col && c.row <= a.bottomRight.row && c.col <= a.bottomRight.col
}

type Area struct {
	topLeft     *Coordinate
	bottomRight *Coordinate
}

func NewArea(coor1, coor2 *Coordinate) *Area {

	tlr, tlc, brr, brc := 0, 0, 0, 0

	if coor1.row > coor2.row {
		tlr = coor2.row
		brr = coor1.row
	} else {
		tlr = coor1.row
		brr = coor2.row
	}

	if coor1.col > coor2.col {
		brc = coor1.col
		tlc = coor2.col
	} else {
		brc = coor2.col
		tlc = coor1.col
	}

	return &Area{
		topLeft:     NewCoordinate(tlr, tlc),
		bottomRight: NewCoordinate(brr, brc),
	}
}

func (a *Area) Expand(c *Coordinate) {
	if c.row > a.bottomRight.row {
		a.bottomRight.row = c.row
	} else if c.row < a.topLeft.row {
		a.topLeft.row = c.row
	}

	if c.col > a.bottomRight.col {
		a.bottomRight.col = c.col
	} else if c.col < a.topLeft.col {
		a.topLeft.col = c.col
	}
}

func (a *Area) Include(r, c int) bool {
	return r >= a.topLeft.row && c >= a.topLeft.col && r <= a.bottomRight.row && c <= a.bottomRight.col
}

type ImageVector []uint8

type ImageMatrix [][]uint8

func NewImageMatrix(r, c int) ImageMatrix {
	imageArray := make([][]uint8, r)
	for i := 0; i < r; i++ {
		imageArray[i] = make([]uint8, c)
	}

	return imageArray
}

func NewImageMatrixWithDefaultValue(r, c int, v uint8) ImageMatrix {
	imageArray := make([][]uint8, r)
	for i := 0; i < r; i++ {
		imageArray[i] = make([]uint8, c)
		for j := 0; j < c; j++ {
			imageArray[i][j] = v
		}
	}

	return imageArray
}

func (i ImageMatrix) Dims() (int, int) {
	return len(i), len(i[0])
}

func (i ImageMatrix) At(r, c int) uint8 {
	return i[r][c]
}

func (i ImageMatrix) Set(r, c int, value uint8) {
	i[r][c] = value
}

func (i ImageMatrix) Slice(sr, er, sc, ec int) ImageMatrix {
	slice := NewImageMatrix(er-sr, ec-sc)

	for r := sr; r < er; r++ {
		for c := sc; c < ec; c++ {
			slice[r-sr][c-sc] = i[r][c]
		}
	}

	return slice
}

func (im ImageMatrix) SliceArea(a *Area) ImageMatrix {
	r, c := a.bottomRight.row-a.topLeft.row, a.bottomRight.col-a.topLeft.col
	slice := NewImageMatrix(r, c)

	for i := 0; i < r; i++ {
		for j := 0; j < c; j++ {
			slice[i][j] = im[a.topLeft.row+i][a.topLeft.col+j]
		}
	}

	return slice
}

func (i ImageMatrix) NNInterpolation(tr, tc int) ImageMatrix {
	r, c := i.Dims()
	rRatio := float64(r) / float64(tr)
	cRatio := float64(c) / float64(tc)
	output := NewImageMatrix(tr, tc)

	for r := 0; r < tr; r++ {
		for c := 0; c < tc; c++ {
			pr := int(math.Floor(float64(r) * rRatio))
			pc := int(math.Floor(float64(c) * cRatio))

			output.Set(r, c, i.At(pr, pc))
		}
	}

	return output
}

func (i ImageMatrix) Pad(top, bottom, left, right int, value uint8) ImageMatrix {
	sr, sc := i.Dims()
	nr := sr + top + bottom
	nc := sc + left + right
	output := NewImageMatrixWithDefaultValue(nr, nc, value)

	for r := 0; r < sr; r++ {
		for c := 0; c < sc; c++ {
			output[r+top][c+left] = i[r][c]
		}
	}

	return output
}

func (i ImageMatrix) Row(r int) ImageVector {
	return i[r]
}

func (i ImageMatrix) Col(c int) ImageVector {
	v := NewImageVector(len(i))

	for j := 0; j < len(i); j++ {
		v[j] = i[j][c]
	}

	return v
}

type ImageMatrixs []ImageMatrix

func (is ImageMatrixs) Average() ImageMatrix {
	l := len(is)
	sr, sc := is[0].Dims()
	output := NewImageMatrix(sr, sc)

	for r := 0; r < sr; r++ {
		for c := 0; c < sc; c++ {
			sum := 0
			for i := 0; i < l; i++ {
				sum += int(is[i][r][c])
			}

			output[r][c] = uint8(sum / l)
		}
	}

	return output
}

func NewImageVector(l int) ImageVector {
	return make([]uint8, l)
}

func (v ImageVector) Sum() uint64 {
	var sum uint64 = 0

	for i := 0; i < len(v); i++ {
		sum += uint64(v[i])
	}

	return sum
}

// ========================= Convolution =========================

type fn func(int, bool) string

// Calculate size after forward
// ds: Data Size
// ks: Kernel / Filter size
// p: Padding
// s: Stride
func sizeAfter(ds, ks, p, s int) int {
	return ((ds - ks + 2*p) / s) + 1
}

func Sigmoid(x float64, deriv bool) float64 {
	if deriv {
		return x * (1 - x)
	}

	return 1 / (1 + math.Exp(-x))
}

func Relu(x float64, deriv bool) float64 {
	if deriv {
		if x > 0 {
			return 1
		} else {
			return 0
		}
	} else {
		if x > 0 {
			return x
		} else {
			return 0
		}
	}
}

func LeakyRelu(x float64, deriv bool) float64 {
	a := 0.001

	if deriv {
		if x > 0 {
			return 1
		} else {
			return a
		}
	} else {
		if x > 0 {
			return x
		} else {
			return a * x
		}
	}
}

func Reshape2DTo2D(x *mat64.Dense, r, c int) *mat64.Dense {
	_, sc := x.Dims()
	o := mat64.NewDense(r, c, nil)

	for i := 0; i < r; i++ {
		for j := 0; j < c; j++ {
			o.Set(i, j, x.At(i/c, (i*c+j)%sc))
		}
	}

	return o
}

func Im2col(x []*mat64.Dense, p, s, kd, kr, kc int) *mat64.Dense {
	dd := len(x)
	_, dc := x[0].Dims()
	dnr := kd * kr * kc
	pl := sizeAfter(dc, kc, p, s)
	dnc := dd * pl

	o := mat64.NewDense(dnr, dnc, nil)

	for i := 0; i < dnr; i++ {
		for j := 0; j < dnc; j++ {
			v := x[i/(dnr/dd)].At(i/kc%dd+(j/pl)*s, i%kc+(j%pl)*s)
			o.Set(i, j, v)
		}
	}

	return o
}

func Col2im(x *mat64.Dense, d, r, c int) []*mat64.Dense {
	_, sc := x.Dims()
	o := make([]*mat64.Dense, d)

	for i := 0; i < d; i++ {
		o[i] = mat64.NewDense(r, c, nil)
		for j := 0; j < r; j++ {
			for k := 0; k < c; k++ {
				o[i].Set(j, k, x.At(i, (j*c+k)%sc))
			}
		}
	}

	return o
}

func ReshapeKernel(x [][]*mat64.Dense) *mat64.Dense {
	n := len(x)
	d := len(x[0])
	r, c := x[0][0].Dims()
	nr := n
	nc := d * r * c

	o := mat64.NewDense(nr, nc, nil)

	for i := 0; i < nr; i++ {
		for j := 0; j < nc; j++ {
			v := x[i][j/(r*c)].At(j/c%r, j%c)
			o.Set(i, j, v)
		}
	}

	return o
}

func Convolve(x, k [][]*mat64.Dense, p, s int) [][]*mat64.Dense {
	kn := len(k)
	kd := len(k[0])
	kr, kc := k[0][0].Dims()
	xn := len(x)
	dr, dc := x[0][0].Dims()

	x_new := make([]*mat64.Dense, xn)
	k_new := ReshapeKernel(k)
	result := make([][]*mat64.Dense, xn)

	pr := sizeAfter(dr, kr, p, s)
	pc := sizeAfter(dc, kc, p, s)

	for i := 0; i < xn; i++ {
		x_new[i] = Im2col(x[i], p, s, kd, kr, kc)
	}

	for i := 0; i < xn; i++ {
		r := &mat64.Dense{}
		r.Mul(k_new, x_new[i])
		result[i] = Col2im(r, kn, pr, pc)
	}

	return result
}

func MaxPool(x *mat64.Dense, fr, fc int) (*mat64.Dense, *mat64.Dense) {
	r, c := x.Dims()
	frc := fr * fc
	nr := sizeAfter(r, fr, 0, fr)
	nc := sizeAfter(c, fc, 0, fc)
	o := mat64.NewDense(nr, nc, nil)
	sw := mat64.NewDense(nr, nc, nil)

	for i := 0; i < nr; i++ {
		for j := 0; j < nc; j++ {
			m := 0.0
			mi := 0

			for k := 0; k < frc; k++ {
				v := x.At(i*fr+k/fr, j*fc+k%fc)

				if m < v {
					m = v
					mi = k
				}
			}

			o.Set(i, j, m)
			sw.Set(i, j, float64(mi))
		}
	}

	return o, sw
}
<commit_msg>Adding erode function<commit_after>package gocr

import (
	"math"

	"github.com/gonum/matrix/mat64"
)

type Coordinate struct {
	row int
	col int
}

func NewCoordinate(r, c int) *Coordinate {
	return &Coordinate{
		row: r,
		col: c,
	}
}

func (c *Coordinate) N() *Coordinate {
	return &Coordinate{
		row: c.row - 1,
		col: c.col,
	}
}

func (c *Coordinate) E() *Coordinate {
	return &Coordinate{
		row: c.row,
		col: c.col + 1,
	}
}

func (c *Coordinate) S() *Coordinate {
	return &Coordinate{
		row: c.row + 1,
		col: c.col,
	}
}

func (c *Coordinate) W() *Coordinate {
	return &Coordinate{
		row: c.row,
		col: c.col - 1,
	}
}

func (c *Coordinate) NE() *Coordinate {
	return &Coordinate{
		row: c.row + 1,
		col: c.col + 1,
	}
}

func (c *Coordinate) SE() *Coordinate {
	return &Coordinate{
		row: c.row - 1,
		col: c.col + 1,
	}
}

func (c *Coordinate) SW() *Coordinate {
	return &Coordinate{
		row: c.row - 1,
		col: c.col - 1,
	}
}

func (c *Coordinate) NW() *Coordinate {
	return &Coordinate{
		row: c.row + 1,
		col: c.col - 1,
	}
}

func (c *Coordinate) IsInside(a *Area) bool {
	if a.topLeft.row == a.bottomRight.row && a.topLeft.col == a.bottomRight.col {
		return false
	}

	return c.row >= a.topLeft.row && c.col >= a.topLeft.col && c.row <= a.bottomRight.row && c.col <= a.bottomRight.col
}

type Area struct {
	topLeft     *Coordinate
	bottomRight *Coordinate
}

func NewArea(coor1, coor2 *Coordinate) *Area {

	tlr, tlc, brr, brc := 0, 0, 0, 0

	if coor1.row > coor2.row {
		tlr = coor2.row
		brr = coor1.row
	} else {
		tlr = coor1.row
		brr = coor2.row
	}

	if coor1.col > coor2.col {
		brc = coor1.col
		tlc = coor2.col
	} else {
		brc = coor2.col
		tlc = coor1.col
	}

	return &Area{
		topLeft:     NewCoordinate(tlr, tlc),
		bottomRight: NewCoordinate(brr, brc),
	}
}

func (a *Area) Expand(c *Coordinate) {
	if c.row > a.bottomRight.row {
		a.bottomRight.row = c.row
	} else if c.row < a.topLeft.row {
		a.topLeft.row = c.row
	}

	if c.col > a.bottomRight.col {
		a.bottomRight.col = c.col
	} else if c.col < a.topLeft.col {
		a.topLeft.col = c.col
	}
}

func (a *Area) Include(r, c int) bool {
	return r >= a.topLeft.row && c >= a.topLeft.col && r <= a.bottomRight.row && c <= a.bottomRight.col
}

type ImageVector []uint8

type ImageMatrix [][]uint8

func NewImageMatrix(r, c int) ImageMatrix {
	imageArray := make([][]uint8, r)
	for i := 0; i < r; i++ {
		imageArray[i] = make([]uint8, c)
	}

	return imageArray
}

func NewImageMatrixWithDefaultValue(r, c int, v uint8) ImageMatrix {
	imageArray := make([][]uint8, r)
	for i := 0; i < r; i++ {
		imageArray[i] = make([]uint8, c)
		for j := 0; j < c; j++ {
			imageArray[i][j] = v
		}
	}

	return imageArray
}

func (i ImageMatrix) Dims() (int, int) {
	return len(i), len(i[0])
}

func (i ImageMatrix) At(r, c int) uint8 {
	return i[r][c]
}

func (i ImageMatrix) AtCoordinate(c *Coordinate) uint8 {
	return i[c.row][c.col]
}

func (i ImageMatrix) Set(r, c int, value uint8) {
	i[r][c] = value
}

func (i ImageMatrix) Slice(sr, er, sc, ec int) ImageMatrix {
	slice := NewImageMatrix(er-sr, ec-sc)

	for r := sr; r < er; r++ {
		for c := sc; c < ec; c++ {
			slice[r-sr][c-sc] = i[r][c]
		}
	}

	return slice
}

func (im ImageMatrix) SliceArea(a *Area) ImageMatrix {
	r, c := a.bottomRight.row-a.topLeft.row, a.bottomRight.col-a.topLeft.col
	slice := NewImageMatrix(r, c)

	for i := 0; i < r; i++ {
		for j := 0; j < c; j++ {
			slice[i][j] = im[a.topLeft.row+i][a.topLeft.col+j]
		}
	}

	return slice
}

func (i ImageMatrix) NNInterpolation(tr, tc int) ImageMatrix {
	r, c := i.Dims()
	rRatio := float64(r) / float64(tr)
	cRatio := float64(c) / float64(tc)
	output := NewImageMatrix(tr, tc)

	for r := 0; r < tr; r++ {
		for c := 0; c < tc; c++ {
			pr := int(math.Floor(float64(r) * rRatio))
			pc := int(math.Floor(float64(c) * cRatio))

			output.Set(r, c, i.At(pr, pc))
		}
	}

	return output
}

// Erode using 4 Neighborhood
func (im ImageMatrix) Erode() {
	r, c := im.Dims()
	a := NewArea(NewCoordinate(0, 0), NewCoordinate(r, c))

	for i := 0; i < r; i++ {
		for j := 0; j < c; j++ {
			n := NewCoordinate(i, j)
			n1, n2, n3, n4 := n.N(), n.E(), n.W(), n.S()

			if n1.IsInside(a) && n2.IsInside(a) && n3.IsInside(a) && n4.IsInside(a) {
				sum := im.AtCoordinate(n) + im.AtCoordinate(n1) + im.AtCoordinate(n2) + im.AtCoordinate(n3) + im.AtCoordinate(n4)
				if sum > 0 {
					im.Set(n.row, n.col, 2)
				}
			}
		}
	}

	for i := 0; i < r; i++ {
		for j := 0; j < c; j++ {
			if im.At(i, j) == 2 {
				im.Set(i, j, 0)
			}
		}
	}

}

func (i ImageMatrix) Pad(top, bottom, left, right int, value uint8) ImageMatrix {
	sr, sc := i.Dims()
	nr := sr + top + bottom
	nc := sc + left + right
	output := NewImageMatrixWithDefaultValue(nr, nc, value)

	for r := 0; r < sr; r++ {
		for c := 0; c < sc; c++ {
			output[r+top][c+left] = i[r][c]
		}
	}

	return output
}

func (i ImageMatrix) Row(r int) ImageVector {
	return i[r]
}

func (i ImageMatrix) Col(c int) ImageVector {
	v := NewImageVector(len(i))

	for j := 0; j < len(i); j++ {
		v[j] = i[j][c]
	}

	return v
}

type ImageMatrixs []ImageMatrix

func (is ImageMatrixs) Average() ImageMatrix {
	l := len(is)
	sr, sc := is[0].Dims()
	output := NewImageMatrix(sr, sc)

	for r := 0; r < sr; r++ {
		for c := 0; c < sc; c++ {
			sum := 0
			for i := 0; i < l; i++ {
				sum += int(is[i][r][c])
			}

			output[r][c] = uint8(sum / l)
		}
	}

	return output
}

func NewImageVector(l int) ImageVector {
	return make([]uint8, l)
}

func (v ImageVector) Sum() uint64 {
	var sum uint64 = 0

	for i := 0; i < len(v); i++ {
		sum += uint64(v[i])
	}

	return sum
}

// ========================= Convolution =========================

type fn func(int, bool) string

// Calculate size after forward
// ds: Data Size
// ks: Kernel / Filter size
// p: Padding
// s: Stride
func sizeAfter(ds, ks, p, s int) int {
	return ((ds - ks + 2*p) / s) + 1
}

func Sigmoid(x float64, deriv bool) float64 {
	if deriv {
		return x * (1 - x)
	}

	return 1 / (1 + math.Exp(-x))
}

func Relu(x float64, deriv bool) float64 {
	if deriv {
		if x > 0 {
			return 1
		} else {
			return 0
		}
	} else {
		if x > 0 {
			return x
		} else {
			return 0
		}
	}
}

func LeakyRelu(x float64, deriv bool) float64 {
	a := 0.001

	if deriv {
		if x > 0 {
			return 1
		} else {
			return a
		}
	} else {
		if x > 0 {
			return x
		} else {
			return a * x
		}
	}
}

func Reshape2DTo2D(x *mat64.Dense, r, c int) *mat64.Dense {
	_, sc := x.Dims()
	o := mat64.NewDense(r, c, nil)

	for i := 0; i < r; i++ {
		for j := 0; j < c; j++ {
			o.Set(i, j, x.At(i/c, (i*c+j)%sc))
		}
	}

	return o
}

func Im2col(x []*mat64.Dense, p, s, kd, kr, kc int) *mat64.Dense {
	dd := len(x)
	_, dc := x[0].Dims()
	dnr := kd * kr * kc
	pl := sizeAfter(dc, kc, p, s)
	dnc := dd * pl

	o := mat64.NewDense(dnr, dnc, nil)

	for i := 0; i < dnr; i++ {
		for j := 0; j < dnc; j++ {
			v := x[i/(dnr/dd)].At(i/kc%dd+(j/pl)*s, i%kc+(j%pl)*s)
			o.Set(i, j, v)
		}
	}

	return o
}

func Col2im(x *mat64.Dense, d, r, c int) []*mat64.Dense {
	_, sc := x.Dims()
	o := make([]*mat64.Dense, d)

	for i := 0; i < d; i++ {
		o[i] = mat64.NewDense(r, c, nil)
		for j := 0; j < r; j++ {
			for k := 0; k < c; k++ {
				o[i].Set(j, k, x.At(i, (j*c+k)%sc))
			}
		}
	}

	return o
}

func ReshapeKernel(x [][]*mat64.Dense) *mat64.Dense {
	n := len(x)
	d := len(x[0])
	r, c := x[0][0].Dims()
	nr := n
	nc := d * r * c

	o := mat64.NewDense(nr, nc, nil)

	for i := 0; i < nr; i++ {
		for j := 0; j < nc; j++ {
			v := x[i][j/(r*c)].At(j/c%r, j%c)
			o.Set(i, j, v)
		}
	}

	return o
}

func Convolve(x, k [][]*mat64.Dense, p, s int) [][]*mat64.Dense {
	kn := len(k)
	kd := len(k[0])
	kr, kc := k[0][0].Dims()
	xn := len(x)
	dr, dc := x[0][0].Dims()

	x_new := make([]*mat64.Dense, xn)
	k_new := ReshapeKernel(k)
	result := make([][]*mat64.Dense, xn)

	pr := sizeAfter(dr, kr, p, s)
	pc := sizeAfter(dc, kc, p, s)

	for i := 0; i < xn; i++ {
		x_new[i] = Im2col(x[i], p, s, kd, kr, kc)
	}

	for i := 0; i < xn; i++ {
		r := &mat64.Dense{}
		r.Mul(k_new, x_new[i])
		result[i] = Col2im(r, kn, pr, pc)
	}

	return result
}

func MaxPool(x *mat64.Dense, fr, fc int) (*mat64.Dense, *mat64.Dense) {
	r, c := x.Dims()
	frc := fr * fc
	nr := sizeAfter(r, fr, 0, fr)
	nc := sizeAfter(c, fc, 0, fc)
	o := mat64.NewDense(nr, nc, nil)
	sw := mat64.NewDense(nr, nc, nil)

	for i := 0; i < nr; i++ {
		for j := 0; j < nc; j++ {
			m := 0.0
			mi := 0

			for k := 0; k < frc; k++ {
				v := x.At(i*fr+k/fr, j*fc+k%fc)

				if m < v {
					m = v
					mi = k
				}
			}

			o.Set(i, j, m)
			sw.Set(i, j, float64(mi))
		}
	}

	return o, sw
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"io"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"

	"gopkg.in/fsnotify.v1"
)

type ColorLogger log.Logger

const (
	logPrefix  = "\033[33m"
	logPostfix = "\033[0m"
)

var (
	watchedRun = ""
	watchedFmt = "."
	noRun      = flag.Bool("n", false, "only run gofmt")
	delay      = flag.Int("d", 1, "delay time before detecting file change")
	isPipe     = false
	exitCode   = 0
	lastReport = make(map[string]time.Time)
)

func getPackageNameAndImport(sourceName string) (packageName string, imports []string) {
	fset := token.NewFileSet() // positions are relative to fset

	// Parse the file containing this very example
	// but stop after processing the imports.
	f, err := parser.ParseFile(fset, sourceName, nil, parser.ImportsOnly)
	if err != nil {
		fmt.Println(err)
		return
	}

	// Print the imports from the file's AST.
	packageName = f.Name.Name

	for _, s := range f.Imports {
		importedPackageName := s.Path.Value[1 : len(s.Path.Value)-1]
		imports = append(imports, importedPackageName)
	}

	return
}

func isGoFile(f os.FileInfo) bool {
	// ignore non-Go files
	name := f.Name()
	return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go")
}

func isMainPackage(sourceName string) bool {
	fset := token.NewFileSet()
	f, _ := parser.ParseFile(fset, sourceName, nil, parser.ImportsOnly)

	return f.Name.Name == "main"
}

func isMainFile(sourceName string) bool {
	fset := token.NewFileSet()

	f, err := parser.ParseFile(fset, sourceName, nil, 0)
	if err != nil {
		return false
	}

	if o := f.Scope.Lookup("main"); f.Name.Name == "main" && o != nil && o.Kind == ast.Fun {
		return true
	}

	return false
}

func visitFile(path string, info os.FileInfo, err error) error {
	log.Println(info.Name())
	if isGoFile(info) {
		format(path)
		if isMainFile(path) {
			fmt.Println("main file -", path)
		}
	}
	return nil
}

func format(path string) error {
	log.Println("gofmt -w", path, logPostfix)
	command := exec.Command("gofmt", "-w", path)
	command.Stdout = os.Stdout
	command.Stderr = os.Stderr
	command.Run()
	return nil
}

func goFiles(path string) (goFiles, mainFiles []string) {
	filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
		if isGoFile(info) {
			goFiles = append(goFiles, path)
			if isMainFile(path) {
				mainFiles = append(mainFiles, path)
			}
		}
		return nil
	})
	return
}

func main() {
	gowatchMain()
	os.Exit(exitCode)
}

func gowatchMain() {
	flag.Parse()

	log.SetPrefix(logPrefix)

	path, err := filepath.Abs(watchedFmt)
	if err != nil {
		panic(err)
	}

	// switch flag.NArg() {
	// case 0:
	// case 1:
	// 	watchedRun = flag.Arg(0)
	// case 2:
	// default:
	// }
	//
	// watchedRun = getMainFile(path)
	// fmt.Println(watchedRun)

	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		panic(err)
	}

	err = watcher.Add(path)
	if err != nil {
		panic(err)
	}
	defer watcher.Close()

	goFiles, mainFiles := goFiles(path)

	// pre run gofmt on found Go files
	for _, f := range goFiles {
		format(f)
	}

	if len(mainFiles) == 1 {
		watchedRun = mainFiles[0]
		log.Println("found a main Go file, watch and run", mainFiles[0], logPostfix)
	} else if len(mainFiles) > 1 {
		watchedRun = mainFiles[0]
		log.Println("found more than one main Go files, watch and run", mainFiles[0], logPostfix)
	} else {
		log.Println("main Go files not found", logPostfix)
	}

	var runCmd *exec.Cmd

	if len(watchedRun) > 0 && !*noRun {
		runCmd = exec.Command("go", "run", watchedRun)
		runCmd.Stdout = os.Stdout
		runCmd.Stderr = os.Stderr
		func(runCmd *exec.Cmd) {
			log.Println("go run", watchedRun, logPostfix)
			runCmd.Run()
			log.Println("exit", watchedRun, logPostfix)
		}(runCmd)
	}

	log.Println("watching", path, logPostfix)

	fi, _ := os.Stdout.Stat()
	isPipe = fi.Mode()&os.ModeNamedPipe != 0

	for event := range watcher.Events {
		if event.Op == fsnotify.Create || event.Op == fsnotify.Write {
			if time.Since(lastReport[event.Name]) < time.Duration(*delay)*time.Second {
				continue
			}
			lastReport[event.Name] = time.Now()
			relPath, _ := filepath.Rel(path, event.Name)
			if isPipe {
				io.WriteString(os.Stdout, relPath+"\n")
			} else {
				if f, _ := os.Stat(event.Name); isGoFile(f) {
					format(event.Name)
					if event.Name == watchedRun && !*noRun {
						if runCmd != nil && runCmd.Process != nil {
							runCmd.Process.Kill()
							log.Println("kill", event.Name, logPostfix)
						}

						runCmd = exec.Command("go", "run", watchedRun)
						runCmd.Stdout = os.Stdout
						runCmd.Stderr = os.Stderr
						func(runCmd *exec.Cmd) {
							log.Println("go run", watchedRun, logPostfix)
							runCmd.Run()
							log.Println("exit", watchedRun, logPostfix)
						}(runCmd)
					}
				}
			}
		}
	}
}
<commit_msg>Add the ability to specify input file for go run<commit_after>package main

import (
	"flag"
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"io"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"

	"gopkg.in/fsnotify.v1"
)

type ColorLogger log.Logger

const (
	logPrefix  = "\033[33m"
	logPostfix = "\033[0m"
)

var (
	watchedRun = ""
	watchedFmt = "."
	noRun      = flag.Bool("n", false, "only run gofmt")
	inFile     = flag.String("in", "", "input file")
	delay      = flag.Int("d", 1, "delay time before detecting file change")
	isPipe     = false
	exitCode   = 0
	lastReport = make(map[string]time.Time)
)

func getPackageNameAndImport(sourceName string) (packageName string, imports []string) {
	fset := token.NewFileSet() // positions are relative to fset

	// Parse the file containing this very example
	// but stop after processing the imports.
	f, err := parser.ParseFile(fset, sourceName, nil, parser.ImportsOnly)
	if err != nil {
		fmt.Println(err)
		return
	}

	// Print the imports from the file's AST.
	packageName = f.Name.Name

	for _, s := range f.Imports {
		importedPackageName := s.Path.Value[1 : len(s.Path.Value)-1]
		imports = append(imports, importedPackageName)
	}

	return
}

func isGoFile(f os.FileInfo) bool {
	// ignore non-Go files
	name := f.Name()
	return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go")
}

func isMainPackage(sourceName string) bool {
	fset := token.NewFileSet()
	f, _ := parser.ParseFile(fset, sourceName, nil, parser.ImportsOnly)

	return f.Name.Name == "main"
}

func isMainFile(sourceName string) bool {
	fset := token.NewFileSet()

	f, err := parser.ParseFile(fset, sourceName, nil, 0)
	if err != nil {
		return false
	}

	if o := f.Scope.Lookup("main"); f.Name.Name == "main" && o != nil && o.Kind == ast.Fun {
		return true
	}

	return false
}

func visitFile(path string, info os.FileInfo, err error) error {
	log.Println(info.Name())
	if isGoFile(info) {
		format(path)
		if isMainFile(path) {
			fmt.Println("main file -", path)
		}
	}
	return nil
}

func format(path string) error {
	log.Println("gofmt -w", path, logPostfix)
	command := exec.Command("gofmt", "-w", path)
	command.Stdout = os.Stdout
	command.Stderr = os.Stderr
	command.Run()
	return nil
}

func goFiles(path string) (goFiles, mainFiles []string) {
	filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
		if isGoFile(info) {
			goFiles = append(goFiles, path)
			if isMainFile(path) {
				mainFiles = append(mainFiles, path)
			}
		}
		return nil
	})
	return
}

var runCmd *exec.Cmd

func goRun(sourceName string) {
	if runCmd != nil && runCmd.Process != nil {
		runCmd.Process.Kill()
	}

	runCmd = exec.Command("go", "run", sourceName)
	go func(runCmd *exec.Cmd) {
		if len(*inFile) > 0 {
			f, err := os.Open(*inFile)
			if err != nil {
				runCmd.Stdin = os.Stdin
			} else {
				runCmd.Stdin = f
				defer f.Close()
			}
			runCmd.Stdin = f
		} else {
			runCmd.Stdin = os.Stdin
		}
		runCmd.Stdout = os.Stdout
		runCmd.Stderr = os.Stderr
		log.Println("go run", watchedRun, logPostfix)
		runCmd.Run()
		log.Println("exit", watchedRun, logPostfix)
	}(runCmd)
}

func main() {
	gowatchMain()
	os.Exit(exitCode)
}

func gowatchMain() {
	flag.Parse()

	log.SetPrefix(logPrefix)

	path, err := filepath.Abs(watchedFmt)
	if err != nil {
		panic(err)
	}

	watcher, err := fsnotify.NewWatcher()
	if err != nil {
		panic(err)
	}

	err = watcher.Add(path)
	if err != nil {
		panic(err)
	}
	defer watcher.Close()

	goFiles, mainFiles := goFiles(path)

	// pre run gofmt on found Go files
	for _, f := range goFiles {
		format(f)
	}

	if len(mainFiles) == 1 {
		watchedRun = mainFiles[0]
		log.Println("found a main Go file, watch and run", mainFiles[0], logPostfix)
	} else if len(mainFiles) > 1 {
		watchedRun = mainFiles[0]
		log.Println("found more than one main Go files, watch and run", mainFiles[0], logPostfix)
	} else {
		log.Println("main Go files not found", logPostfix)
	}

	if len(watchedRun) > 0 && !*noRun {
		goRun(watchedRun)
	}

	log.Println("watching", path, logPostfix)

	fi, _ := os.Stdout.Stat()
	isPipe = fi.Mode()&os.ModeNamedPipe != 0

	for event := range watcher.Events {
		if event.Op == fsnotify.Create || event.Op == fsnotify.Write {
			if time.Since(lastReport[event.Name]) < time.Duration(*delay)*time.Second {
				continue
			}
			lastReport[event.Name] = time.Now()
			relPath, _ := filepath.Rel(path, event.Name)
			if isPipe {
				io.WriteString(os.Stdout, relPath+"\n")
			} else {
				if f, _ := os.Stat(event.Name); isGoFile(f) {
					format(event.Name)
					if event.Name == watchedRun && !*noRun {
						goRun(watchedRun)
					}
				}
			}
		}
	}
}
<|endoftext|>


<commit_before>// Copyright 2013, 2014 Peter Vasil, Tomo Krajina. All
// rights reserved. Use of this source code is governed
// by a BSD-style license that can be found in the
// LICENSE file.

package gpx

import (
	"bytes"
	"encoding/xml"
	"errors"
	"io"
	"os"
	"strings"
	"time"

	"golang.org/x/net/html/charset"
)

const formattingTimelayout = "2006-01-02T15:04:05Z"

// parsingTimelayouts defines a list of possible time formats
var parsingTimelayouts = []string{
	"2006-01-02T15:04:05.000Z",
	formattingTimelayout,
	"2006-01-02T15:04:05+00:00",
	"2006-01-02T15:04:05",
	"2006-01-02 15:04:05Z",
	"2006-01-02 15:04:05",
}

func init() {
	/*
		fmt.Println("----------------------------------------------------------------------------------------------------")
		fmt.Println("This API is experimental, it *will* change")
		fmt.Println("----------------------------------------------------------------------------------------------------")
	*/
}

//ToXmlParams contains settings for xml transformation
type ToXmlParams struct {
	Version string
	Indent  bool
}

//ToXml returns the xml representation of the GPX object.
//Params are optional, you can set null to use GPXs Version and no indentation.
func ToXml(g *GPX, params ToXmlParams) ([]byte, error) {
	version := g.Version
	if len(params.Version) > 0 {
		version = params.Version
	}
	indentation := params.Indent

	var replacemends map[string]string
	var gpxDoc interface{}
	if version == "1.0" {
		gpxDoc = convertToGpx10Models(g)
	} else if version == "1.1" {
		gpxDoc, replacemends = convertToGpx11Models(g)
	} else {
		g.Version = "1.1"
		gpxDoc, replacemends = convertToGpx11Models(g)
	}

	var buffer bytes.Buffer
	buffer.WriteString(xml.Header)
	if indentation {
		b, err := xml.MarshalIndent(gpxDoc, "", "	")
		if err != nil {
			return nil, err
		}
		buffer.Write(b)
	} else {
		b, err := xml.Marshal(gpxDoc)
		if err != nil {
			return nil, err
		}
		buffer.Write(b)
	}

	byts := buffer.Bytes()

	for replKey, replVal := range replacemends {
		byts = bytes.Replace(byts, []byte(replKey), []byte(replVal), -1)
	}

	return byts, nil
}

func guessGPXVersion(bytes []byte) (string, error) {
	bytesCount := 1000
	if len(bytes) < 1000 {
		bytesCount = len(bytes)
	}

	startOfDocument := string(bytes[:bytesCount])

	parts := strings.Split(startOfDocument, "<gpx")
	if len(parts) <= 1 {
		return "", errors.New("invalid GPX file, cannot find version")
	}
	parts = strings.Split(parts[1], "version=")

	if len(parts) <= 1 {
		return "", errors.New("invalid GPX file, cannot find version")
	}

	if len(parts[1]) < 10 {
		return "", errors.New("invalid GPX file, cannot find version")
	}

	result := parts[1][1:4]

	return result, nil
}

func parseGPXTime(timestr string) (*time.Time, error) {
	if strings.Contains(timestr, ".") {
		// Probably seconds with milliseconds
		timestr = strings.Split(timestr, ".")[0]
	}
	timestr = strings.Trim(timestr, " \t\n\r")
	for _, timeLayout := range parsingTimelayouts {
		t, err := time.Parse(timeLayout, timestr)

		if err == nil {
			return &t, nil
		}
	}

	return nil, errors.New("Cannot parse " + timestr)
}

func formatGPXTime(time *time.Time) string {
	if time == nil {
		return ""
	}
	if time.Year() <= 1 {
		// Invalid date:
		return ""
	}
	return time.Format(formattingTimelayout)
}

//ParseFile parses a gpx file and returns a GPX object
func ParseFile(fileName string) (*GPX, error) {
	f, err := os.Open(fileName)
	if err != nil {
		return nil, err
	}

	defer f.Close()

	return Parse(f)
}

//ParseBytes parses GPX from bytes
func ParseBytes(buf []byte) (*GPX, error) {
	return Parse(bytes.NewBuffer(buf))
}

//ParseBytes parses GPX from bytes
func Parse(inReader io.Reader) (*GPX, error) {
	// at most 1000 bytes will make guessGPXVersion happy
	buf := make([]byte, 1000)

	n, err := inReader.Read(buf)
	if err != nil {
		return nil, err
	}
	buf = buf[:n]
	version, err := guessGPXVersion(buf)
	if err != nil {
		// Unknown version, try with 1.1
		version = "1.1"
	}

	reader := io.MultiReader(bytes.NewReader(buf), inReader)
	decoder := xml.NewDecoder(reader)
	decoder.CharsetReader = charset.NewReaderLabel

	if version == "1.0" {

		g := &gpx10Gpx{}

		err = decoder.Decode(&g)
		if err != nil {
			return nil, err
		}

		return convertFromGpx10Models(g), nil
	}

	if version == "1.1" {

		g := &gpx11Gpx{}

		err = decoder.Decode(&g)
		if err != nil {
			return nil, err
		}

		return convertFromGpx11Models(g), nil
	}

	return nil, errors.New("Invalid version:" + version)
}

//ParseString parses GPX from string
func ParseString(str string) (*GPX, error) {
	return ParseBytes([]byte(str))
}
<commit_msg>optimize bridge code<commit_after>// Copyright 2013, 2014 Peter Vasil, Tomo Krajina. All
// rights reserved. Use of this source code is governed
// by a BSD-style license that can be found in the
// LICENSE file.

package gpx

import (
	"bytes"
	"encoding/xml"
	"errors"
	"io"
	"os"
	"strings"
	"time"

	"golang.org/x/net/html/charset"
)

const formattingTimelayout = "2006-01-02T15:04:05Z"

// parsingTimelayouts defines a list of possible time formats
var parsingTimelayouts = []string{
	"2006-01-02T15:04:05.000Z",
	formattingTimelayout,
	"2006-01-02T15:04:05+00:00",
	"2006-01-02T15:04:05",
	"2006-01-02 15:04:05Z",
	"2006-01-02 15:04:05",
}

func init() {
	/*
		fmt.Println("----------------------------------------------------------------------------------------------------")
		fmt.Println("This API is experimental, it *will* change")
		fmt.Println("----------------------------------------------------------------------------------------------------")
	*/
}

//ToXmlParams contains settings for xml transformation
type ToXmlParams struct {
	Version string
	Indent  bool
}

//ToXml returns the xml representation of the GPX object.
//Params are optional, you can set null to use GPXs Version and no indentation.
func ToXml(g *GPX, params ToXmlParams) ([]byte, error) {
	version := g.Version
	if len(params.Version) > 0 {
		version = params.Version
	}
	indentation := params.Indent

	var replacemends map[string]string
	var gpxDoc interface{}
	if version == "1.0" {
		gpxDoc = convertToGpx10Models(g)
	} else if version == "1.1" {
		gpxDoc, replacemends = convertToGpx11Models(g)
	} else {
		g.Version = "1.1"
		gpxDoc, replacemends = convertToGpx11Models(g)
	}

	var buffer bytes.Buffer
	buffer.WriteString(xml.Header)
	if indentation {
		b, err := xml.MarshalIndent(gpxDoc, "", "	")
		if err != nil {
			return nil, err
		}
		buffer.Write(b)
	} else {
		b, err := xml.Marshal(gpxDoc)
		if err != nil {
			return nil, err
		}
		buffer.Write(b)
	}

	byts := buffer.Bytes()

	for replKey, replVal := range replacemends {
		byts = bytes.Replace(byts, []byte(replKey), []byte(replVal), -1)
	}

	return byts, nil
}

func guessGPXVersion(bytes []byte) (string, error) {
	bytesCount := 1000
	if len(bytes) < 1000 {
		bytesCount = len(bytes)
	}

	startOfDocument := string(bytes[:bytesCount])

	parts := strings.Split(startOfDocument, "<gpx")
	if len(parts) <= 1 {
		return "", errors.New("invalid GPX file, cannot find version")
	}
	parts = strings.Split(parts[1], "version=")

	if len(parts) <= 1 {
		return "", errors.New("invalid GPX file, cannot find version")
	}

	if len(parts[1]) < 10 {
		return "", errors.New("invalid GPX file, cannot find version")
	}

	result := parts[1][1:4]

	return result, nil
}

func parseGPXTime(timestr string) (*time.Time, error) {
	if strings.Contains(timestr, ".") {
		// Probably seconds with milliseconds
		timestr = strings.Split(timestr, ".")[0]
	}
	timestr = strings.Trim(timestr, " \t\n\r")
	for _, timeLayout := range parsingTimelayouts {
		t, err := time.Parse(timeLayout, timestr)

		if err == nil {
			return &t, nil
		}
	}

	return nil, errors.New("Cannot parse " + timestr)
}

func formatGPXTime(time *time.Time) string {
	if time == nil {
		return ""
	}
	if time.Year() <= 1 {
		// Invalid date:
		return ""
	}
	return time.Format(formattingTimelayout)
}

//ParseFile parses a gpx file and returns a GPX object
func ParseFile(fileName string) (*GPX, error) {
	f, err := os.Open(fileName)
	if err != nil {
		return nil, err
	}

	defer f.Close()

	return Parse(f)
}

//ParseBytes parses GPX from bytes
func ParseBytes(buf []byte) (*GPX, error) {
	return Parse(bytes.NewReader(buf))
}

//Parse parses GPX from io.Reader
func Parse(inReader io.Reader) (*GPX, error) {
	// at most 1000 bytes will make guessGPXVersion happy
	buf := make([]byte, 1000)

	n, err := inReader.Read(buf)
	if err != nil {
		return nil, err
	}
	buf = buf[:n]
	version, err := guessGPXVersion(buf)
	if err != nil {
		// Unknown version, try with 1.1
		version = "1.1"
	}

	reader := io.MultiReader(bytes.NewReader(buf), inReader)
	decoder := xml.NewDecoder(reader)
	decoder.CharsetReader = charset.NewReaderLabel

	if version == "1.0" {

		g := &gpx10Gpx{}

		err = decoder.Decode(&g)
		if err != nil {
			return nil, err
		}

		return convertFromGpx10Models(g), nil
	}

	if version == "1.1" {

		g := &gpx11Gpx{}

		err = decoder.Decode(&g)
		if err != nil {
			return nil, err
		}

		return convertFromGpx11Models(g), nil
	}

	return nil, errors.New("Invalid version:" + version)
}

//ParseString parses GPX from string
func ParseString(str string) (*GPX, error) {
	return Parse(strings.NewReader(str))
}
<|endoftext|>


<commit_before>//	Copyright 2013 slowfei And The Contributors All rights reserved.
//
//	Software Source Code License Agreement (BSD License)
//
//  Create on 2013-8-24
//  Update on 2013-10-31
//  Email  slowfei@foxmail.com
//  Home   http://www.slowfei.com

//	go sql entity utils
package main

import (
	"database/sql"
	"errors"
	"flag"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"os"
	"regexp"
	"strings"
	"text/template"
	"time"
)

type FieldStruct struct {
	FieldName    string
	FieldType    string
	FieldComment string
}

type TableStruct struct {
	TableName      string
	TableComment   string
	Fields         []FieldStruct
	TableRefernces []string
	GetSet         bool
}

type FileOutStruct struct {
	CreateTime  time.Time
	DBName      string
	PackageName string
	Imports     []string
	Entitys     []TableStruct
}

const (
	APP_NAME = "gosqleu"
	VERSION  = "1.0"
)

var (
	importTime  = false
	connection  = flag.String("conn", "", "database connection information [user:password@tcp(localhost:3306)/dbname]")
	isGetSet    = flag.Bool("getset", true, "is struct field out get set func")
	packageName = flag.String("package", "main", "package name default main")
	filterTable = flag.String("filter-table", "", "filter table name [table1,table]")
	outFilePath = flag.String("path", "", "out file path")
	connRex     = regexp.MustCompile(`\w+(:\w)?@((tcp(\(.+:\d{1,5}\))?)?|(unix\(\/(.*)([^/]*)\w+\)))/\w+((\\?|&+)(.+?)=([^&]*))?`)

	fileTmpl, _ = template.New("entityfile").Funcs(template.FuncMap{"FuncName": FuncName, "ParamLower": ParamLower, "MysqltypeToGotype": MysqltypeToGotype}).Parse(fileLayout)
	fileLayout  = `//
//	create time {{.CreateTime}}
//	` + APP_NAME + ` version ` + VERSION + `

//	database {{.DBName}}
package {{.PackageName}}
{{range .Imports}}
import "{{.}}"
{{end}}{{with .Entitys}}{{range .}}
/*====================================*
 	{{.TableName}} table

 	{{.TableComment}}
 *====================================*/
type {{FuncName .TableName}} struct{
	{{with .Fields}}{{range .}}
	{{.FieldName}}	{{MysqltypeToGotype .FieldType}}	// {{.FieldComment}}{{end}}{{end}}
	{{range .TableRefernces}}
	*{{.}}{{end}}
}
{{$TempTableName := .TableName}}{{if .GetSet}}{{with .Fields}}{{range .}}
/* get set {{.FieldComment}} */
func (this *{{$TempTableName}}) Get{{FuncName .FieldName}}() {{MysqltypeToGotype .FieldType}}{
	return this.{{.FieldName}}
}
func (this *{{$TempTableName}}) Set{{FuncName .FieldName}}({{ParamLower .FieldName}} {{MysqltypeToGotype .FieldType}}){
	this.{{.FieldName}} = {{ParamLower .FieldName}}
}
{{end}}{{end}}{{end}}{{end}}

{{end}}
`
)

func FuncName(name string) string {
	spl := strings.Split(name, "_")
	joinName := ""

	for _, s := range spl {
		joinName += strings.Title(s)
	}

	return joinName
}

func ParamLower(name string) string {
	name = strings.ToLower(name)
	name = strings.Replace(name, "_", "", -1)
	return name
}

func MysqltypeToGotype(typeName string) string {
	typeName = strings.ToLower(typeName)
	switch {
	case 0 <= strings.Index(typeName, "bit"):
		return "bool"
	case 0 <= strings.Index(typeName, "int"):
		result := ""
		if 0 <= strings.Index(typeName, "unsigned") {
			result = "u"
		}
		switch {
		case 0 <= strings.Index(typeName, "tinyint"):
			result += "int8"
		case 0 <= strings.Index(typeName, "smallint"):
			result += "int16"
		case 0 <= strings.Index(typeName, "mediumint"):
			result += "int32"
		case 0 <= strings.Index(typeName, "bigint"):
			result += "int64"
		default:
			result += "int"
		}
		return result
	case 0 <= strings.Index(typeName, "real"):
		return "float32"
	case 0 <= strings.Index(typeName, "float"):
		return "float32"
	case 0 <= strings.Index(typeName, "double"):
		return "float64"
	case 0 <= strings.Index(typeName, "decimal"):
		return "float64"
	case 0 <= strings.Index(typeName, "numeric"):
		return "float64"
	case 0 <= strings.Index(typeName, "date"):
		return "time.Time"
	case 0 <= strings.Index(typeName, "time"):
		return "time.Time"
	case 0 <= strings.Index(typeName, "year"):
		return "time.Time"
	case 0 <= strings.Index(typeName, "blob"):
		return "[]byte"
	default:
		return "string"
	}

	return "string"
}

func getFieldInfos(sqldb *sql.DB, tableName string) []FieldStruct {
	rows, err := sqldb.Query(`
select COLUMN_NAME,COLUMN_TYPE,COLUMN_COMMENT from information_schema.COLUMNS
	where TABLE_SCHEMA = database() and TABLE_NAME = ?
`, tableName)
	if nil != err {
		fmt.Println("Query Tables Error:", err)
		return nil
	}
	defer rows.Close()

	fields := make([]FieldStruct, 0)
	for rows.Next() {
		fs := FieldStruct{}
		rows.Scan(&fs.FieldName, &fs.FieldType, &fs.FieldComment)
		if 0 <= strings.Index(strings.ToLower(fs.FieldType), "time") || 0 <= strings.Index(strings.ToLower(fs.FieldType), "date") {
			importTime = true
		}
		fields = append(fields, fs)
	}

	return fields
}

func getTables(sqldb *sql.DB) []TableStruct {

	rows, err := sqldb.Query(`
select TABLE_NAME as name,TABLE_COMMENT as comment,
(select GROUP_CONCAT(REFERENCED_TABLE_NAME SEPARATOR ',') from information_schema.REFERENTIAL_CONSTRAINTS where TABLE_NAME=name) as refnames
from information_schema.TABLES where TABLE_SCHEMA = database();
`)
	if nil != err {
		fmt.Println("Query Tables Error:", err)
		return nil
	}
	defer rows.Close()

	tables := make([]TableStruct, 0)

	for rows.Next() {
		ts := TableStruct{}
		ts.GetSet = *isGetSet
		refstr := ""
		rows.Scan(&ts.TableName, &ts.TableComment, &refstr)

		isFilter := false
		for _, filterName := range strings.Split(*filterTable, ",") {
			if strings.ToLower(filterName) == strings.ToLower(ts.TableName) {
				isFilter = true
				break
			}
		}

		if isFilter {
			continue
		}

		if 0 != len(refstr) {
			ts.TableRefernces = strings.Split(refstr, ",")
		}
		fmt.Printf("Table (%v) ...\n", ts.TableName)
		ts.Fields = getFieldInfos(sqldb, ts.TableName)
		tables = append(tables, ts)
	}

	return tables
}

func getFileOut(sqldb *sql.DB) (FileOutStruct, error) {
	fileOut := FileOutStruct{}

	var dbName string
	e := sqldb.QueryRow("SELECT database()").Scan(&dbName)
	switch {
	case e == sql.ErrNoRows:
		return fileOut, errors.New("No database with name.")
	case e != nil:
		return fileOut, e
	}

	if 0 == len(dbName) {
		return fileOut, errors.New("Get not database name.")
	}

	fileOut.Entitys = getTables(sqldb)
	fileOut.CreateTime = time.Now()
	if importTime {
		fileOut.Imports = []string{"time"}
	}
	fileOut.PackageName = *packageName
	fileOut.DBName = dbName

	return fileOut, nil
}

func main() {
	flag.Parse()

	conn := ""
	if 0 != len(flag.Args()) {
		conn = flag.Arg(0)
	}

	if 0 == len(conn) || !connRex.MatchString(conn) {
		if !connRex.MatchString(*connection) {
			fmt.Println("error: connection = $gosqleu [user:password@tcp(localhost:3306)/dbname]\nor other params:")
			flag.PrintDefaults()
			return
		} else {
			conn = *connection
		}
	}

	db, err := sql.Open("mysql", conn)
	if nil != err {
		fmt.Println("mysql database connection error:", err)
		return
	}
	defer db.Close()

	fileOut, e := getFileOut(db)
	if nil != e {
		fmt.Println(e)
		return
	}

	filePath := *outFilePath
	if 0 == len(filePath) {
		filePath = fileOut.DBName + ".go"
	}
	if '/' == filePath[len(filePath)-1] {
		filePath += fileOut.DBName + ".go"
	}
	fmt.Println("out file...")
	newFile, errFile := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0660)
	if nil != errFile {
		fmt.Println(errFile)
		return
	}

	tplErr := fileTmpl.Execute(newFile, fileOut)
	if nil != tplErr {
		fmt.Println(tplErr)
		return
	}
	fmt.Println("success.")
	fmt.Println("path: ", newFile.Name())

}
<commit_msg>update time<commit_after>//	Copyright 2013 slowfei And The Contributors All rights reserved.
//
//	Software Source Code License Agreement (BSD License)
//
//  Create on 2013-11-30
//  Update on 2013-12-01
//  Email  slowfei@foxmail.com
//  Home   http://www.slowfei.com

//	go sql entity utils
package main

import (
	"database/sql"
	"errors"
	"flag"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"os"
	"regexp"
	"strings"
	"text/template"
	"time"
)

type FieldStruct struct {
	FieldName    string
	FieldType    string
	FieldComment string
}

type TableStruct struct {
	TableName      string
	TableComment   string
	Fields         []FieldStruct
	TableRefernces []string
	GetSet         bool
}

type FileOutStruct struct {
	CreateTime  time.Time
	DBName      string
	PackageName string
	Imports     []string
	Entitys     []TableStruct
}

const (
	APP_NAME = "gosqleu"
	VERSION  = "1.0"
)

var (
	importTime  = false
	connection  = flag.String("conn", "", "database connection information [user:password@tcp(localhost:3306)/dbname]")
	isGetSet    = flag.Bool("getset", true, "is struct field out get set func")
	packageName = flag.String("package", "main", "package name default main")
	filterTable = flag.String("filter-table", "", "filter table name [table1,table]")
	outFilePath = flag.String("path", "", "out file path")
	connRex     = regexp.MustCompile(`\w+(:\w)?@((tcp(\(.+:\d{1,5}\))?)?|(unix\(\/(.*)([^/]*)\w+\)))/\w+((\\?|&+)(.+?)=([^&]*))?`)

	fileTmpl, _ = template.New("entityfile").Funcs(template.FuncMap{"FuncName": FuncName, "ParamLower": ParamLower, "MysqltypeToGotype": MysqltypeToGotype}).Parse(fileLayout)
	fileLayout  = `//
//	create time {{.CreateTime}}
//	` + APP_NAME + ` version ` + VERSION + `

//	database {{.DBName}}
package {{.PackageName}}
{{range .Imports}}
import "{{.}}"
{{end}}{{with .Entitys}}{{range .}}
/*====================================*
 	{{.TableName}} table

 	{{.TableComment}}
 *====================================*/
type {{FuncName .TableName}} struct{
	{{with .Fields}}{{range .}}
	{{.FieldName}}	{{MysqltypeToGotype .FieldType}}	// {{.FieldComment}}{{end}}{{end}}
	{{range .TableRefernces}}
	*{{.}}{{end}}
}
{{$TempTableName := .TableName}}{{if .GetSet}}{{with .Fields}}{{range .}}
/* get set {{.FieldComment}} */
func (this *{{$TempTableName}}) Get{{FuncName .FieldName}}() {{MysqltypeToGotype .FieldType}}{
	return this.{{.FieldName}}
}
func (this *{{$TempTableName}}) Set{{FuncName .FieldName}}({{ParamLower .FieldName}} {{MysqltypeToGotype .FieldType}}){
	this.{{.FieldName}} = {{ParamLower .FieldName}}
}
{{end}}{{end}}{{end}}{{end}}

{{end}}
`
)

func FuncName(name string) string {
	spl := strings.Split(name, "_")
	joinName := ""

	for _, s := range spl {
		joinName += strings.Title(s)
	}

	return joinName
}

func ParamLower(name string) string {
	name = strings.ToLower(name)
	name = strings.Replace(name, "_", "", -1)
	return name
}

func MysqltypeToGotype(typeName string) string {
	typeName = strings.ToLower(typeName)
	switch {
	case 0 <= strings.Index(typeName, "bit"):
		return "bool"
	case 0 <= strings.Index(typeName, "int"):
		result := ""
		if 0 <= strings.Index(typeName, "unsigned") {
			result = "u"
		}
		switch {
		case 0 <= strings.Index(typeName, "tinyint"):
			result += "int8"
		case 0 <= strings.Index(typeName, "smallint"):
			result += "int16"
		case 0 <= strings.Index(typeName, "mediumint"):
			result += "int32"
		case 0 <= strings.Index(typeName, "bigint"):
			result += "int64"
		default:
			result += "int"
		}
		return result
	case 0 <= strings.Index(typeName, "real"):
		return "float32"
	case 0 <= strings.Index(typeName, "float"):
		return "float32"
	case 0 <= strings.Index(typeName, "double"):
		return "float64"
	case 0 <= strings.Index(typeName, "decimal"):
		return "float64"
	case 0 <= strings.Index(typeName, "numeric"):
		return "float64"
	case 0 <= strings.Index(typeName, "date"):
		return "time.Time"
	case 0 <= strings.Index(typeName, "time"):
		return "time.Time"
	case 0 <= strings.Index(typeName, "year"):
		return "time.Time"
	case 0 <= strings.Index(typeName, "blob"):
		return "[]byte"
	default:
		return "string"
	}

	return "string"
}

func getFieldInfos(sqldb *sql.DB, tableName string) []FieldStruct {
	rows, err := sqldb.Query(`
select COLUMN_NAME,COLUMN_TYPE,COLUMN_COMMENT from information_schema.COLUMNS
	where TABLE_SCHEMA = database() and TABLE_NAME = ?
`, tableName)
	if nil != err {
		fmt.Println("Query Tables Error:", err)
		return nil
	}
	defer rows.Close()

	fields := make([]FieldStruct, 0)
	for rows.Next() {
		fs := FieldStruct{}
		rows.Scan(&fs.FieldName, &fs.FieldType, &fs.FieldComment)
		if 0 <= strings.Index(strings.ToLower(fs.FieldType), "time") || 0 <= strings.Index(strings.ToLower(fs.FieldType), "date") {
			importTime = true
		}
		fields = append(fields, fs)
	}

	return fields
}

func getTables(sqldb *sql.DB) []TableStruct {

	rows, err := sqldb.Query(`
select TABLE_NAME as name,TABLE_COMMENT as comment,
(select GROUP_CONCAT(REFERENCED_TABLE_NAME SEPARATOR ',') from information_schema.REFERENTIAL_CONSTRAINTS where TABLE_NAME=name) as refnames
from information_schema.TABLES where TABLE_SCHEMA = database();
`)
	if nil != err {
		fmt.Println("Query Tables Error:", err)
		return nil
	}
	defer rows.Close()

	tables := make([]TableStruct, 0)

	for rows.Next() {
		ts := TableStruct{}
		ts.GetSet = *isGetSet
		refstr := ""
		rows.Scan(&ts.TableName, &ts.TableComment, &refstr)

		isFilter := false
		for _, filterName := range strings.Split(*filterTable, ",") {
			if strings.ToLower(filterName) == strings.ToLower(ts.TableName) {
				isFilter = true
				break
			}
		}

		if isFilter {
			continue
		}

		if 0 != len(refstr) {
			ts.TableRefernces = strings.Split(refstr, ",")
		}
		fmt.Printf("Table (%v) ...\n", ts.TableName)
		ts.Fields = getFieldInfos(sqldb, ts.TableName)
		tables = append(tables, ts)
	}

	return tables
}

func getFileOut(sqldb *sql.DB) (FileOutStruct, error) {
	fileOut := FileOutStruct{}

	var dbName string
	e := sqldb.QueryRow("SELECT database()").Scan(&dbName)
	switch {
	case e == sql.ErrNoRows:
		return fileOut, errors.New("No database with name.")
	case e != nil:
		return fileOut, e
	}

	if 0 == len(dbName) {
		return fileOut, errors.New("Get not database name.")
	}

	fileOut.Entitys = getTables(sqldb)
	fileOut.CreateTime = time.Now()
	if importTime {
		fileOut.Imports = []string{"time"}
	}
	fileOut.PackageName = *packageName
	fileOut.DBName = dbName

	return fileOut, nil
}

func main() {
	flag.Parse()

	conn := ""
	if 0 != len(flag.Args()) {
		conn = flag.Arg(0)
	}

	if 0 == len(conn) || !connRex.MatchString(conn) {
		if !connRex.MatchString(*connection) {
			fmt.Println("error: connection = $gosqleu [user:password@tcp(localhost:3306)/dbname]\nor other params:")
			flag.PrintDefaults()
			return
		} else {
			conn = *connection
		}
	}

	db, err := sql.Open("mysql", conn)
	if nil != err {
		fmt.Println("mysql database connection error:", err)
		return
	}
	defer db.Close()

	fileOut, e := getFileOut(db)
	if nil != e {
		fmt.Println(e)
		return
	}

	filePath := *outFilePath
	if 0 == len(filePath) {
		filePath = fileOut.DBName + ".go"
	}
	if '/' == filePath[len(filePath)-1] {
		filePath += fileOut.DBName + ".go"
	}
	fmt.Println("out file...")
	newFile, errFile := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0660)
	if nil != errFile {
		fmt.Println(errFile)
		return
	}

	tplErr := fileTmpl.Execute(newFile, fileOut)
	if nil != tplErr {
		fmt.Println(tplErr)
		return
	}
	fmt.Println("success.")
	fmt.Println("path: ", newFile.Name())

}
<|endoftext|>


<commit_before>package godbg

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"
	"regexp"
	"runtime/debug"
	"strings"
)

var rxDbgLine, _ = regexp.Compile(`^.*[Vv]on[Cc](?:/prog/git)?/senvgo/main.go:(\d+)\s`)
var rxDbgFnct, _ = regexp.Compile(`^\s+(?:com/VonC/senvgo)?(?:\.\(([^\)]+)\))?\.?([^:]+)`)

// http://stackoverflow.com/a/23554672/6309 https://vividcortex.com/blog/2013/12/03/go-idiom-package-and-object/
// you design a type with methods as usual, and then you also place matching functions at the package level itself.
// These functions simply delegate to a default instance of the type that’s a private package-level variable, created in an init() function.

// Pdbg allows to print debug message with indent and function name added
type Pdbg struct {
	bout *bytes.Buffer
	berr *bytes.Buffer
	sout *bufio.Writer
	serr *bufio.Writer
}

// Out returns a writer for normal messages.
// By default, os.StdOut
func Out() io.Writer {
	return pdbg.Out()
}

// Out returns a writer for normal messages for a given pdbg instance.
// By default, os.StdOut
func (pdbg *Pdbg) Out() io.Writer {
	if pdbg.sout == nil {
		return os.Stdout
	}
	return pdbg.sout
}

// Err returns a writer for error messages.
// By default, os.StdErr
func Err() io.Writer {
	return pdbg.Err()
}

// Err returns a writer for error messages for a given pdbg instance.
// By default, os.StdErr
func (pdbg *Pdbg) Err() io.Writer {
	if pdbg.serr == nil {
		return os.Stderr
	}
	return pdbg.serr
}

// global pdbg used for printing
var pdbg = &Pdbg{}

// Option set an option for a Pdbg
// http://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis
type Option func(*Pdbg)

// SetBuffers is an option for replacing stdout and stderr by
// bytes buffers (in a bufio.Writer)
func SetBuffers(apdbg *Pdbg) {
	apdbg.bout = bytes.NewBuffer(nil)
	apdbg.sout = bufio.NewWriter(apdbg.bout)
	apdbg.berr = bytes.NewBuffer(nil)
	apdbg.serr = bufio.NewWriter(apdbg.berr)
}

// NewPdbg creates a PDbg instance, with options
func NewPdbg(options ...Option) *Pdbg {
	newpdbg := &Pdbg{}
	for _, option := range options {
		option(newpdbg)
	}
	return newpdbg
}

func pdbgInc(scanner *bufio.Scanner, line string) string {
	m := rxDbgLine.FindSubmatchIndex([]byte(line))
	if len(m) == 0 {
		return ""
	}
	dbgLine := line[m[2]:m[3]]
	// fmt.Printf("line '%v', m '%+v'\n", line, m)
	scanner.Scan()
	line = scanner.Text()
	mf := rxDbgFnct.FindSubmatchIndex([]byte(line))
	// fmt.Printf("lineF '%v', mf '%+v'\n", line, mf)
	if len(mf) == 0 {
		return ""
	}
	dbgFnct := ""
	if mf[2] > -1 {
		dbgFnct = line[mf[2]:mf[3]]
	}
	if dbgFnct != "" {
		dbgFnct = dbgFnct + "."
	}
	dbgFnct = dbgFnct + line[mf[4]:mf[5]]

	return dbgFnct + ":" + dbgLine
}

func pdbgExcluded(dbg string) bool {
	if strings.Contains(dbg, "ReadConfig:") {
		return false
	}
	return false
}

// Pdbgf uses global Pdbg variable for printing strings, with indent and function name
func Pdbgf(format string, args ...interface{}) string {
	msg := fmt.Sprintf(format+"\n", args...)
	msg = strings.TrimSpace(msg)
	bstack := bytes.NewBuffer(debug.Stack())
	// fmt.Printf("%+v", bstack)

	scanner := bufio.NewScanner(bstack)
	pmsg := ""
	depth := 0
	for scanner.Scan() {
		line := scanner.Text()
		if strings.Contains(line, "smartystreets") {
			break
		}
		m := rxDbgLine.FindSubmatchIndex([]byte(line))
		if len(m) == 0 {
			continue
		}
		if depth > 0 && depth < 4 {
			dbg := pdbgInc(scanner, line)
			if dbg == "" {
				continue
			}
			if depth == 1 {
				if pdbgExcluded(dbg) {
					return ""
				}
				pmsg = "[" + dbg + "]"
			} else {
				pmsg = pmsg + " (" + dbg + ")"
			}
		}
		depth = depth + 1
	}
	spaces := ""
	if depth >= 2 {
		spaces = strings.Repeat(" ", depth-2)
	}
	res := pmsg
	pmsg = spaces + pmsg
	msg = pmsg + "\n" + spaces + "  " + msg + "\n"
	// fmt.Printf("MSG '%v'\n", msg)
	fmt.Fprint(os.Stderr, fmt.Sprint(msg))
	return res
}
<commit_msg>Reset buffers, and flush writers<commit_after>package godbg

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"
	"regexp"
	"runtime/debug"
	"strings"
)

var rxDbgLine, _ = regexp.Compile(`^.*[Vv]on[Cc](?:/prog/git)?/senvgo/main.go:(\d+)\s`)
var rxDbgFnct, _ = regexp.Compile(`^\s+(?:com/VonC/senvgo)?(?:\.\(([^\)]+)\))?\.?([^:]+)`)

// http://stackoverflow.com/a/23554672/6309 https://vividcortex.com/blog/2013/12/03/go-idiom-package-and-object/
// you design a type with methods as usual, and then you also place matching functions at the package level itself.
// These functions simply delegate to a default instance of the type that’s a private package-level variable, created in an init() function.

// Pdbg allows to print debug message with indent and function name added
type Pdbg struct {
	bout *bytes.Buffer
	berr *bytes.Buffer
	sout *bufio.Writer
	serr *bufio.Writer
}

// Out returns a writer for normal messages.
// By default, os.StdOut
func Out() io.Writer {
	return pdbg.Out()
}

// Out returns a writer for normal messages for a given pdbg instance.
// By default, os.StdOut
func (pdbg *Pdbg) Out() io.Writer {
	if pdbg.sout == nil {
		return os.Stdout
	}
	return pdbg.sout
}

// Err returns a writer for error messages.
// By default, os.StdErr
func Err() io.Writer {
	return pdbg.Err()
}

// Err returns a writer for error messages for a given pdbg instance.
// By default, os.StdErr
func (pdbg *Pdbg) Err() io.Writer {
	if pdbg.serr == nil {
		return os.Stderr
	}
	return pdbg.serr
}

// global pdbg used for printing
var pdbg = &Pdbg{}

// Option set an option for a Pdbg
// http://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis
type Option func(*Pdbg)

// SetBuffers is an option for replacing stdout and stderr by
// bytes buffers (in a bufio.Writer)
func SetBuffers(apdbg *Pdbg) {
	apdbg.bout = bytes.NewBuffer(nil)
	apdbg.sout = bufio.NewWriter(apdbg.bout)
	apdbg.berr = bytes.NewBuffer(nil)
	apdbg.serr = bufio.NewWriter(apdbg.berr)
}

// NewPdbg creates a PDbg instance, with options
func NewPdbg(options ...Option) *Pdbg {
	newpdbg := &Pdbg{}
	for _, option := range options {
		option(newpdbg)
	}
	return newpdbg
}

// ResetIOs reset the out and err buffer
// (unless they were the default stdout and stderr,
// in which case it does nothing)
func (pdbg *Pdbg) ResetIOs() {
	if pdbg.sout != nil {
		pdbg.bout = bytes.NewBuffer(nil)
		pdbg.sout.Reset(pdbg.bout)
		pdbg.berr = bytes.NewBuffer(nil)
		pdbg.serr.Reset(pdbg.berr)
	}
}

// FlushIOs flushes the sout and serr bufio.Writer
func (pdbg *Pdbg) FlushIOs() {
	pdbg.sout.Flush()
	pdbg.serr.Flush()
}

func pdbgInc(scanner *bufio.Scanner, line string) string {
	m := rxDbgLine.FindSubmatchIndex([]byte(line))
	if len(m) == 0 {
		return ""
	}
	dbgLine := line[m[2]:m[3]]
	// fmt.Printf("line '%v', m '%+v'\n", line, m)
	scanner.Scan()
	line = scanner.Text()
	mf := rxDbgFnct.FindSubmatchIndex([]byte(line))
	// fmt.Printf("lineF '%v', mf '%+v'\n", line, mf)
	if len(mf) == 0 {
		return ""
	}
	dbgFnct := ""
	if mf[2] > -1 {
		dbgFnct = line[mf[2]:mf[3]]
	}
	if dbgFnct != "" {
		dbgFnct = dbgFnct + "."
	}
	dbgFnct = dbgFnct + line[mf[4]:mf[5]]

	return dbgFnct + ":" + dbgLine
}

func pdbgExcluded(dbg string) bool {
	if strings.Contains(dbg, "ReadConfig:") {
		return false
	}
	return false
}

// Pdbgf uses global Pdbg variable for printing strings, with indent and function name
func Pdbgf(format string, args ...interface{}) string {
	msg := fmt.Sprintf(format+"\n", args...)
	msg = strings.TrimSpace(msg)
	bstack := bytes.NewBuffer(debug.Stack())
	// fmt.Printf("%+v", bstack)

	scanner := bufio.NewScanner(bstack)
	pmsg := ""
	depth := 0
	for scanner.Scan() {
		line := scanner.Text()
		if strings.Contains(line, "smartystreets") {
			break
		}
		m := rxDbgLine.FindSubmatchIndex([]byte(line))
		if len(m) == 0 {
			continue
		}
		if depth > 0 && depth < 4 {
			dbg := pdbgInc(scanner, line)
			if dbg == "" {
				continue
			}
			if depth == 1 {
				if pdbgExcluded(dbg) {
					return ""
				}
				pmsg = "[" + dbg + "]"
			} else {
				pmsg = pmsg + " (" + dbg + ")"
			}
		}
		depth = depth + 1
	}
	spaces := ""
	if depth >= 2 {
		spaces = strings.Repeat(" ", depth-2)
	}
	res := pmsg
	pmsg = spaces + pmsg
	msg = pmsg + "\n" + spaces + "  " + msg + "\n"
	// fmt.Printf("MSG '%v'\n", msg)
	fmt.Fprint(os.Stderr, fmt.Sprint(msg))
	return res
}
<|endoftext|>