<commit_before>/// List of Earthquakes
/// Queries USGS json service for a list of earthquakes and returns
/// a list with watered down information.
///
/// The list can be filtered by country code.
/// For filtering by country, the latitude/longitude of the earthquake is used
/// to get the country code from api.geonames.org
///
/// Example
/// latitude: -116.6920013, longitude: 33.5480003
/// http://api.geonames.org/countryCode?lat=33.54&lng=-116.69&username=demo ==> US

package main

import (
    "fmt"
    "log"
	"net/http"
    //"strings"
	"encoding/json"
)

// Constants with html code for our web page
const (
    pageTop = `
        <!DOCTYPE html>

            <title>earthquakes</title>
            <meta charset="utf-8">
            <meta name="viewport" content="width=device-width, initial-scale=1">

            <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">

Earthquakes

Shows latest earthquakes around the world
`
    form = `
                <form role="form" action="/" method="POST">

Choose time span

                        <input type="radio" name="opttime" id="timeHour" value="hour">Past Hour

                        <input type="radio" name="opttime" id="timeDay" value="day" checked="checked">Past Day

                        <input type="radio" name="opttime" id="timeWeek" value="week">Past 7 Days

                        <input type="radio" name="opttime" id="timeMonth" value="month">Past 30 Days

Choose magnitude

                        <input type="radio" name="optmagnitude" id="magnitudeSignificant" value="significant" checked="checked">Significant

                        <input type="radio" name="optmagnitude" id="magnitude4_5" value="4_5">M4.5+

                        <input type="radio" name="optmagnitude" id="magnitude2_5" value="2_5">M2.5+

                        <input type="radio" name="optmagnitude" id="magnitude1_0" value="1_0">M1.0+

                        <input type="radio" name="optmagnitude" id="magnitudeAll" value="all">All

                    <button type="submit" class="btn btn-success" >Show</button>
                </form>`
    pageBottom = `

        `
    anError = `<br /><p class="text-danger">%s</p>`
)

// Enums for time spans
type timespan int;
const (
	hour timespan = iota
	day
	week
	month
)

// Enums for magnitudes
type magnitude int;
const (
	significant magnitude = iota
	m4_5
	m2_5
	m1_0
	all
)

// Struct holding the user's options and list of earthquakes
type earthquakes struct {
    ts timespan
    mag magnitude
    title string
    count int
}

func main() {
    // Setup the web server handling the requests
    http.HandleFunc("/", homePage)
    if err := http.ListenAndServe("0.0.0.0:8080", nil); err != nil {
        log.Fatal("failed to start server", err)
    }
}

// Handling the call to the home page; i.e. handling everything because there
// is no other page!
func homePage(writer http.ResponseWriter, request *http.Request) {
    err := request.ParseForm() // Must be called before writing the response
    fmt.Fprint(writer, pageTop, form)

    if err != nil {
        fmt.Fprintf(writer, anError, err)
    } else {
        if ts, mag, msg, ok := processRequest(request); ok {
            //fmt.Fprint(writer, "
timespan: ", ts, "
")
            //fmt.Fprint(writer, "
magnitude: ", mag, "
")
            if quakes, err := getQuakes(ts, mag); err != nil {
                fmt.Fprintf(writer, anError, err.Error())
            } else {
                fmt.Fprint(writer, formatQuakes(quakes))
            }
        } else if msg != "" {
            fmt.Fprintf(writer, anError, msg)
        }
    }

    fmt.Fprint(writer, pageBottom)
}

// Process the http request
func processRequest(request *http.Request) (timespan, magnitude, string, bool) {

    inputTs := request.Form.Get("opttime");
    inputMag := request.Form.Get("optmagnitude");

	log.Print("ts: ", inputTs)
	log.Print("mag: ", inputMag)

	var ts timespan
	var mag magnitude

	switch inputTs {
	    case "hour":
	        ts = hour
	    case "day":
	        ts = day
	    case "week":
	        ts = week
	    case "month":
	        ts = month
	    default:
	        var msg string
	        if inputTs != "" {
	            msg = "invalid timespan " + "'" + inputTs + "'"
	        }
            return day, significant, msg, false
	}

	switch inputMag {
	    case "significant":
	        mag = significant
	    case "4_5":
	        mag = m4_5
	    case "2_5":
	        mag = m2_5
	    case "1_0":
	        mag = m1_0
	    case "all":
	        mag = all
	    default:
	        var msg string
	        if inputMag != "" {
	            msg = "invalid magnitude " + "'" + inputMag + "'"
	        }
	        return day, significant, msg, false
	}

	return ts, mag, "", true
}

// get the earthquakes from the USGS website
func getQuakes(ts timespan, mag magnitude) (earthquakes, error) {
    url := "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/"

    switch mag {
        case significant:
            url += "significant"
        case m4_5:
            url += "4.5"
        case m2_5:
            url += "2.5"
        case m1_0:
            url += "1.0"
        case all:
            url += "all"
        default:
            url += ""
    }

    switch ts {
        case hour:
        url += "_hour"
        case day:
        url += "_day"
        case week:
        url += "_week"
        case month:
        url += "_month"
        default:
        url += ""
    }

    url += ".geojson"

    resp, err := http.Get(url)
    if err != nil {
        return earthquakes{}, err
    }

    defer resp.Body.Close()

    var d geojson

    if err := json.NewDecoder(resp.Body).Decode(&d); err != nil {
        return earthquakes{}, err
    }
	log.Print("title: ", d.Metadata.Title)

    var quakes earthquakes
    quakes.ts = ts
    quakes.mag = mag
    quakes.title = d.Metadata.Title
    quakes.count = d.Metadata.Count

    return quakes, nil
}

// format earthquakes in HTML
func formatQuakes(quakes earthquakes) string {
    return fmt.Sprintf(`

%s

count: %d
`, quakes.title, quakes.count)
}

// The GeoJSON struct
type geojson struct {
    Metadata struct {
        Url   string `json:"url"`
        Title string `json:"title"`
        Count int `json:"count"`
    } `json:"metadata"`
}<commit_msg>Display table of earthquake's according to user's selection<commit_after>/// List of Earthquakes
/// Queries USGS json service for a list of earthquakes and returns
/// a list with watered down information.
///
/// The list can be filtered by country code.
/// For filtering by country, the latitude/longitude of the earthquake is used
/// to get the country code from api.geonames.org
///
/// Example
/// latitude: -116.6920013, longitude: 33.5480003
/// http://api.geonames.org/countryCode?lat=33.54&lng=-116.69&username=demo ==> US

package main

import (
    "fmt"
    "time"
    "log"
	"net/http"
    //"strings"
	"encoding/json"
)

// Constants with html code for our web page
const (
    pageTop = `
        <!DOCTYPE html>

            <title>earthquakes</title>
            <meta charset="utf-8">
            <meta name="viewport" content="width=device-width, initial-scale=1">

            <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">

Earthquakes

Shows latest earthquakes around the world
`
    form = `
                <form role="form" action="/" method="POST">

Choose time span

                        <input type="radio" name="opttime" id="timeHour" value="hour">Past Hour

                        <input type="radio" name="opttime" id="timeDay" value="day" checked="checked">Past Day

                        <input type="radio" name="opttime" id="timeWeek" value="week">Past 7 Days

                        <input type="radio" name="opttime" id="timeMonth" value="month">Past 30 Days

Choose magnitude

                        <input type="radio" name="optmagnitude" id="magnitudeSignificant" value="significant" checked="checked">Significant

                        <input type="radio" name="optmagnitude" id="magnitude4_5" value="4_5">M4.5+

                        <input type="radio" name="optmagnitude" id="magnitude2_5" value="2_5">M2.5+

                        <input type="radio" name="optmagnitude" id="magnitude1_0" value="1_0">M1.0+

                        <input type="radio" name="optmagnitude" id="magnitudeAll" value="all">All

                    <button type="submit" class="btn btn-success" >Show</button>
                </form>`
    pageBottom = `

        `
    anError = `<br /><p class="text-danger">%s</p>`
)

// Enums for time spans
type timespan int;
const (
	hour timespan = iota
	day
	week
	month
)

// Enums for magnitudes
type magnitude int;
const (
	significant magnitude = iota
	m4_5
	m2_5
	m1_0
	all
)

// Struct holding the user's options and list of earthquakes
type earthquakes struct {
    ts timespan
    mag magnitude
    title string
    count int
    quakes []earthquake
}

type earthquake struct {
    mag float32
    place string
    time string
    url string
}

func main() {
    // Setup the web server handling the requests
    http.HandleFunc("/", homePage)
    if err := http.ListenAndServe("0.0.0.0:8080", nil); err != nil {
        log.Fatal("failed to start server", err)
    }
}

// Handling the call to the home page; i.e. handling everything because there
// is no other page!
func homePage(writer http.ResponseWriter, request *http.Request) {
    err := request.ParseForm() // Must be called before writing the response
    fmt.Fprint(writer, pageTop, form)

    if err != nil {
        fmt.Fprintf(writer, anError, err)
    } else {
        if ts, mag, msg, ok := processRequest(request); ok {
            //fmt.Fprint(writer, "
timespan: ", ts, "
")
            //fmt.Fprint(writer, "
magnitude: ", mag, "
")
            if quakes, err := getQuakes(ts, mag); err != nil {
                fmt.Fprintf(writer, anError, err.Error())
            } else {
                fmt.Fprint(writer, formatQuakes(quakes))
            }
        } else if msg != "" {
            fmt.Fprintf(writer, anError, msg)
        }
    }

    fmt.Fprint(writer, pageBottom)
}

// Process the http request
func processRequest(request *http.Request) (timespan, magnitude, string, bool) {

    inputTs := request.Form.Get("opttime");
    inputMag := request.Form.Get("optmagnitude");

	log.Print("ts: ", inputTs)
	log.Print("mag: ", inputMag)

	var ts timespan
	var mag magnitude

	switch inputTs {
	    case "hour":
	        ts = hour
	    case "day":
	        ts = day
	    case "week":
	        ts = week
	    case "month":
	        ts = month
	    default:
	        var msg string
	        if inputTs != "" {
	            msg = "invalid timespan " + "'" + inputTs + "'"
	        }
            return day, significant, msg, false
	}

	switch inputMag {
	    case "significant":
	        mag = significant
	    case "4_5":
	        mag = m4_5
	    case "2_5":
	        mag = m2_5
	    case "1_0":
	        mag = m1_0
	    case "all":
	        mag = all
	    default:
	        var msg string
	        if inputMag != "" {
	            msg = "invalid magnitude " + "'" + inputMag + "'"
	        }
	        return day, significant, msg, false
	}

	return ts, mag, "", true
}

// get the earthquakes from the USGS website
func getQuakes(ts timespan, mag magnitude) (earthquakes, error) {
    url := "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/"

    switch mag {
        case significant:
            url += "significant"
        case m4_5:
            url += "4.5"
        case m2_5:
            url += "2.5"
        case m1_0:
            url += "1.0"
        case all:
            url += "all"
        default:
            url += ""
    }

    switch ts {
        case hour:
        url += "_hour"
        case day:
        url += "_day"
        case week:
        url += "_week"
        case month:
        url += "_month"
        default:
        url += ""
    }

    url += ".geojson"

    resp, err := http.Get(url)
    if err != nil {
        return earthquakes{}, err
    }

    defer resp.Body.Close()

    var d geojson

    if err := json.NewDecoder(resp.Body).Decode(&d); err != nil {
        return earthquakes{}, err
    }
	log.Print("title: ", d.Metadata.Title)

    var quakes earthquakes
    quakes.ts = ts
    quakes.mag = mag
    quakes.title = d.Metadata.Title
    quakes.count = d.Metadata.Count
    quakes.quakes = make([]earthquake, d.Metadata.Count)

    for i, q := range d.Features {
        quakes.quakes[i].mag = q.Properties.Mag
        quakes.quakes[i].place = q.Properties.Place
        quakes.quakes[i].time = fmt.Sprint(time.Unix(q.Properties.Time/1000, 0))
        quakes.quakes[i].url = q.Properties.Url
    }

    return quakes, nil
}

// format earthquakes in HTML
func formatQuakes(quakes earthquakes) string {
    quakesHtml := fmt.Sprintf(`

%s

count: %d

Magnitude	Place	Time	Link

`,
                quakes.title, quakes.count)

    for _, q := range quakes.quakes {
        quakesHtml += fmt.Sprintf(`

%.2f	%s	%s	%s
`,
                    q.mag, q.place, q.time, q.url, q.url)
    }

    quakesHtml += fmt.Sprintf(`

`)

    return quakesHtml
}

// The GeoJSON struct with the fields we are interested in
type geojson struct {
    Metadata struct {
        Url   string `json:"url"`
        Title string `json:"title"`
        Count int `json:"count"`
    } `json:"metadata"`
    Features [] struct {
        Properties struct {
            Mag float32 `json:"mag"`
            Place string `json:"place"`
            Time int64 `json:"time"`
            Tz int64 `json:"tz"`
            Url string `json:"url"`
        } `json:"properties"`
    } `json:"features"`
}<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math/rand"
	"sync"
	"time"

	"github.com/vbauerster/mpb/v7"
	"github.com/vbauerster/mpb/v7/decor"
)

const (
	totalBars = 32
)

func main() {
	var wg sync.WaitGroup
	p := mpb.New(
		mpb.WithWaitGroup(&wg),
		mpb.WithRefreshRate(50*time.Millisecond),
	)
	wg.Add(totalBars)

	for i := 0; i < totalBars; i++ {
		name := fmt.Sprintf("Bar#%02d: ", i)
		total := rand.Intn(320) + 10
		bar := p.AddBar(int64(total),
			mpb.PrependDecorators(
				decor.Name(name),
				decor.Elapsed(decor.ET_STYLE_GO, decor.WCSyncSpace),
			),
			mpb.AppendDecorators(
				decor.OnComplete(
					decor.Percentage(decor.WC{W: 5}), "done",
				),
			),
		)

		go func() {
			defer wg.Done()
			rng := rand.New(rand.NewSource(time.Now().UnixNano()))
			max := 100 * time.Millisecond
			for !bar.Completed() {
				time.Sleep(time.Duration(rng.Intn(10)+1) * max / 10)
				bar.Increment()
			}
		}()
	}

	p.Wait()
}
<commit_msg>stress example: use default rr<commit_after>package main

import (
	"fmt"
	"math/rand"
	"sync"
	"time"

	"github.com/vbauerster/mpb/v7"
	"github.com/vbauerster/mpb/v7/decor"
)

const (
	totalBars = 32
)

func main() {
	var wg sync.WaitGroup
	p := mpb.New(mpb.WithWaitGroup(&wg))
	wg.Add(totalBars)

	for i := 0; i < totalBars; i++ {
		name := fmt.Sprintf("Bar#%02d: ", i)
		total := rand.Intn(320) + 10
		bar := p.AddBar(int64(total),
			mpb.PrependDecorators(
				decor.Name(name),
				decor.Elapsed(decor.ET_STYLE_GO, decor.WCSyncSpace),
			),
			mpb.AppendDecorators(
				decor.OnComplete(
					decor.Percentage(decor.WC{W: 5}), "done",
				),
			),
		)

		go func() {
			defer wg.Done()
			rng := rand.New(rand.NewSource(time.Now().UnixNano()))
			max := 100 * time.Millisecond
			for !bar.Completed() {
				time.Sleep(time.Duration(rng.Intn(10)+1) * max / 10)
				bar.Increment()
			}
		}()
	}

	p.Wait()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/fairlyblank/md2min"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

// 定义一个访问者结构体
type Visitor struct{}

func (self *Visitor) md2html(arg map[string]string) error {
	from := arg["from"]
	to := arg["to"]
	err := filepath.Walk(from+"/", func(path string, f os.FileInfo, err error) error {
		if f == nil {
			return err
		}
		if f.IsDir() {
			return nil
		}
		if (f.Mode() & os.ModeSymlink) > 0 {
			return nil
		}
		if !strings.HasSuffix(f.Name(), ".md") {
			return nil
		}

		file, err := os.Open(path)
		if err != nil {
			return err
		}

		input_byte, _ := ioutil.ReadAll(file)
		input := string(input_byte)
		input = regexp.MustCompile(`\[(.*?)\]\(<?(.*?)\.md>?\)`).ReplaceAllString(input, "[$1](<$2.html>)")

		if f.Name() == "README.md" {
			input = regexp.MustCompile(`https:\/\/github\.com\/astaxie\/build-web-application-with-golang\/blob\/master\/`).ReplaceAllString(input, "")
		}

		// 以#开头的行，在#后增加空格
		// 以#开头的行, 删除多余的空格
		input = FixHeader(input)

		// 删除页面链接
		input = RemoveFooterLink(input)

		var out *os.File
		filename := strings.Replace(f.Name(), ".md", ".html", -1)
		fmt.Println(to + "/" + filename)
		if out, err = os.Create(to + "/" + filename); err != nil {
			fmt.Fprintf(os.Stderr, "Error creating %s: %v", f.Name(), err)
			os.Exit(-1)
		}
		defer out.Close()
		md := md2min.New("none")
		err = md.Parse([]byte(input), out)
		if err != nil {
			fmt.Fprintln(os.Stderr, "Parsing Error", err)
			os.Exit(-1)
		}

		return nil
	})
	return err
}

func FixHeader(input string) string {
	re_header := regexp.MustCompile(`(?m)^#.+$`)
	re_sub := regexp.MustCompile(`^(#+)\s*(.+)$`)
	fixer := func(header string) string {
		s := re_sub.FindStringSubmatch(header)
		return s[1] + " " + s[2]
	}
	return re_header.ReplaceAllStringFunc(input, fixer)
}

func RemoveFooterLink(input string) string {
	re_footer := regexp.MustCompile(`(?m)^#{2,} links.*?\n(.+\n)*`)
	return re_footer.ReplaceAllString(input, "")
}

func main() {
	tmp := os.Getenv("TMP")
	if tmp == "" {
		tmp = "."
	}

	workdir := os.Getenv("WORKDIR")
	if workdir == "" {
		workdir = "."
	}

	arg := map[string]string{
		"from": workdir,
		"to":   tmp,
	}

	v := &Visitor{}
	err := v.md2html(arg)
	if err != nil {
		fmt.Printf("filepath.Walk() returned %v\n", err)
	}
}
<commit_msg>fix missing images by removing the tailing part of the image paths on building the epub<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strings"

	"github.com/fairlyblank/md2min"
)

// 定义一个访问者结构体
type Visitor struct{}

func (self *Visitor) md2html(arg map[string]string) error {
	from := arg["from"]
	to := arg["to"]
	err := filepath.Walk(from+"/", func(path string, f os.FileInfo, err error) error {
		if f == nil {
			return err
		}
		if f.IsDir() {
			return nil
		}
		if (f.Mode() & os.ModeSymlink) > 0 {
			return nil
		}
		if !strings.HasSuffix(f.Name(), ".md") {
			return nil
		}

		file, err := os.Open(path)
		if err != nil {
			return err
		}

		input_byte, _ := ioutil.ReadAll(file)
		input := string(input_byte)
		input = regexp.MustCompile(`\[(.*?)\]\(<?(.*?)\.md>?\)`).ReplaceAllString(input, "[$1](<$2.html>)")

		if f.Name() == "README.md" {
			input = regexp.MustCompile(`https:\/\/github\.com\/astaxie\/build-web-application-with-golang\/blob\/master\/`).ReplaceAllString(input, "")
		}

		// 以#开头的行，在#后增加空格
		// 以#开头的行, 删除多余的空格
		input = FixHeader(input)

		// 删除页面链接
		input = RemoveFooterLink(input)

		// remove image suffix
		input = RemoveImageLinkSuffix(input)

		var out *os.File
		filename := strings.Replace(f.Name(), ".md", ".html", -1)
		fmt.Println(to + "/" + filename)
		if out, err = os.Create(to + "/" + filename); err != nil {
			fmt.Fprintf(os.Stderr, "Error creating %s: %v", f.Name(), err)
			os.Exit(-1)
		}
		defer out.Close()
		md := md2min.New("none")
		err = md.Parse([]byte(input), out)
		if err != nil {
			fmt.Fprintln(os.Stderr, "Parsing Error", err)
			os.Exit(-1)
		}

		return nil
	})
	return err
}

func FixHeader(input string) string {
	re_header := regexp.MustCompile(`(?m)^#.+$`)
	re_sub := regexp.MustCompile(`^(#+)\s*(.+)$`)
	fixer := func(header string) string {
		s := re_sub.FindStringSubmatch(header)
		return s[1] + " " + s[2]
	}
	return re_header.ReplaceAllStringFunc(input, fixer)
}

func RemoveFooterLink(input string) string {
	re_footer := regexp.MustCompile(`(?m)^#{2,} links.*?\n(.+\n)*`)
	return re_footer.ReplaceAllString(input, "")
}

func RemoveImageLinkSuffix(input string) string {
	re_footer := regexp.MustCompile(`png\?raw=true`)
	return re_footer.ReplaceAllString(input, "png")
}

func main() {
	tmp := os.Getenv("TMP")
	if tmp == "" {
		tmp = "."
	}

	workdir := os.Getenv("WORKDIR")
	if workdir == "" {
		workdir = "."
	}

	arg := map[string]string{
		"from": workdir,
		"to":   tmp,
	}

	v := &Visitor{}
	err := v.md2html(arg)
	if err != nil {
		fmt.Printf("filepath.Walk() returned %v\n", err)
	}
}
<|endoftext|>


<commit_before>// Package edit implements a command line editor.
package edit

import (
	"fmt"
	"os"
	"syscall"

	"github.com/elves/elvish/errutil"
	"github.com/elves/elvish/eval"
	"github.com/elves/elvish/logutil"
	"github.com/elves/elvish/parse"
	"github.com/elves/elvish/store"
	"github.com/elves/elvish/sys"
)

var Logger = logutil.GetLogger("[edit] ")

const (
	lackEOLRune = '\u23ce'
	lackEOL     = "\033[7m" + string(lackEOLRune) + "\033[m"
)

// Editor keeps the status of the line editor.
type Editor struct {
	file   *os.File
	writer *writer
	reader *Reader
	sigs   chan os.Signal
	store  *store.Store
	evaler *eval.Evaler
	cmdSeq int
	editorState
}

type editorState struct {
	// States used during ReadLine. Reset at the beginning of ReadLine.
	active                bool
	savedTermios          *sys.Termios
	tokens                []Token
	prompt, rprompt, line string
	dot                   int
	notifications         []string
	tips                  []string
	mode                  bufferMode
	completion            *completion
	completionLines       int
	navigation            *navigation
	history               historyState
	historyListing        *historyListing
	isExternal            map[string]bool
	// Used for builtins.
	lastKey    Key
	nextAction action
}

type bufferMode int

const (
	modeInsert bufferMode = iota
	modeCommand
	modeCompletion
	modeNavigation
	modeHistory
	modeHistoryListing
)

type actionType int

const (
	noAction actionType = iota
	reprocessKey
	exitReadLine
)

// LineRead is the result of ReadLine. Exactly one member is non-zero, making
// it effectively a tagged union.
type LineRead struct {
	Line string
	EOF  bool
	Err  error
}

// NewEditor creates an Editor.
func NewEditor(file *os.File, sigs chan os.Signal, ev *eval.Evaler, st *store.Store) *Editor {
	seq := -1
	if st != nil {
		var err error
		seq, err = st.NextCmdSeq()
		if err != nil {
			// TODO(xiaq): Also report the error
			seq = -1
		}
	}

	ed := &Editor{
		file:   file,
		writer: newWriter(file),
		reader: NewReader(file),
		sigs:   sigs,
		store:  st,
		evaler: ev,
		cmdSeq: seq,
	}
	ev.AddModule("le", makeModule(ed))
	return ed
}

func (ed *Editor) flash() {
	// TODO implement fish-like flash effect
}

func (ed *Editor) addTip(format string, args ...interface{}) {
	ed.tips = append(ed.tips, fmt.Sprintf(format, args...))
}

func (ed *Editor) notify(format string, args ...interface{}) {
	ed.notifications = append(ed.notifications, fmt.Sprintf(format, args...))
}

func (ed *Editor) refresh(fullRefresh bool) error {
	// Re-lex the line, unless we are in modeCompletion
	name := "[interacitve]"
	src := ed.line
	if ed.mode != modeCompletion {
		n, _ /*err*/ := parse.Parse(src)
		if n == nil {
			ed.tokens = []Token{{ParserError, src, nil, ""}}
		} else {
			ed.tokens = tokenize(src, n)
			_, err := ed.evaler.Compile(name, src, n)
			if err != nil {
				if err, ok := err.(*errutil.ContextualError); ok {
					ed.addTip("compiler error highlighted")
					p := err.Pos()
					for i, token := range ed.tokens {
						if token.Node.Begin() <= p && p < token.Node.End() {
							ed.tokens[i].MoreStyle += styleForCompilerError
							break
						}
					}
				}
			}
		}
		for i, t := range ed.tokens {
			for _, stylist := range stylists {
				ed.tokens[i].MoreStyle += stylist(t.Node, ed)
			}
		}
	}
	return ed.writer.refresh(&ed.editorState, fullRefresh)
}

// acceptCompletion accepts currently selected completion candidate.
func (ed *Editor) acceptCompletion() {
	c := ed.completion
	if 0 <= c.current && c.current < len(c.candidates) {
		accepted := c.candidates[c.current].source.text
		ed.insertAtDot(accepted)
	}
	ed.completion = nil
	ed.mode = modeInsert
}

// insertAtDot inserts text at the dot and moves the dot after it.
func (ed *Editor) insertAtDot(text string) {
	ed.line = ed.line[:ed.dot] + text + ed.line[ed.dot:]
	ed.dot += len(text)
}

func setupTerminal(file *os.File) (*sys.Termios, error) {
	fd := int(file.Fd())
	term, err := sys.NewTermiosFromFd(fd)
	if err != nil {
		return nil, fmt.Errorf("can't get terminal attribute: %s", err)
	}

	savedTermios := term.Copy()

	term.SetICanon(false)
	term.SetEcho(false)
	term.SetVMin(1)
	term.SetVTime(0)

	err = term.ApplyToFd(fd)
	if err != nil {
		return nil, fmt.Errorf("can't set up terminal attribute: %s", err)
	}

	/*
		err = sys.FlushInput(fd)
		if err != nil {
			return nil, fmt.Errorf("can't flush input: %s", err)
		}
	*/

	return savedTermios, nil
}

// startReadLine prepares the terminal for the editor.
func (ed *Editor) startReadLine() error {
	savedTermios, err := setupTerminal(ed.file)
	if err != nil {
		return err
	}
	ed.savedTermios = savedTermios

	_, width := sys.GetWinsize(int(ed.file.Fd()))
	// Turn on autowrap, write lackEOL along with enough padding to fill the
	// whole screen. If the cursor was in the first column, we end up in the
	// same line (just off the line boundary); otherwise we are now in the next
	// line. We now rewind to the first column and erase anything there. The
	// final effect is that a lackEOL gets written if and only if the cursor
	// was not in the first column.
	fmt.Fprintf(ed.file, "\033[?7h%s%*s\r \r", lackEOL, width-WcWidth(lackEOLRune), "")

	// Turn off autowrap. The edito has its own wrapping mechanism. Doing
	// wrapping manually means that when the actual width of some characters
	// are greater than what our wcwidth implementation tells us, characters at
	// the end of that line gets hidden -- compared to pushed to the next line,
	// which is more disastrous.
	ed.file.WriteString("\033[?7l")
	// Turn on SGR-style mouse tracking.
	ed.file.WriteString("\033[?1000;1006h")
	return nil
}

// finishReadLine puts the terminal in a state suitable for other programs to
// use.
func (ed *Editor) finishReadLine(addError func(error)) {
	ed.mode = modeInsert
	ed.tips = nil
	ed.completion = nil
	ed.navigation = nil
	ed.dot = len(ed.line)
	// TODO Perhaps make it optional to NOT clear the rprompt
	ed.rprompt = ""
	addError(ed.refresh(false))
	ed.file.WriteString("\n")

	// ed.reader.Stop()
	ed.reader.Quit()

	// Turn on autowrap.
	ed.file.WriteString("\033[?7h")
	// Turn off mouse tracking.
	ed.file.WriteString("\033[?1000;1006l")

	// restore termios
	err := ed.savedTermios.ApplyToFd(int(ed.file.Fd()))

	if err != nil {
		addError(fmt.Errorf("can't restore terminal attribute: %s", err))
	}
	ed.savedTermios = nil
	ed.editorState = editorState{}
}

// ReadLine reads a line interactively.
func (ed *Editor) ReadLine(prompt, rprompt func() string) (lr LineRead) {
	ed.editorState = editorState{active: true}
	isExternalCh := make(chan map[string]bool, 1)
	go getIsExternal(ed.evaler, isExternalCh)

	ed.writer.resetOldBuf()
	go ed.reader.Run()

	err := ed.startReadLine()
	if err != nil {
		return LineRead{Err: err}
	}
	defer ed.finishReadLine(func(err error) {
		if err != nil {
			lr.Err = errutil.CatError(lr.Err, err)
		}
	})

MainLoop:
	for {
		ed.prompt = prompt()
		ed.rprompt = rprompt()

		err := ed.refresh(false)
		if err != nil {
			return LineRead{Err: err}
		}

		ed.tips = nil

		select {
		case m := <-isExternalCh:
			ed.isExternal = m
		case sig := <-ed.sigs:
			// TODO(xiaq): Maybe support customizable handling of signals
			switch sig {
			case syscall.SIGINT:
				// Start over
				ed.editorState = editorState{
					savedTermios: ed.savedTermios,
					isExternal:   ed.isExternal,
				}
				goto MainLoop
			case syscall.SIGWINCH:
				continue MainLoop
			case syscall.SIGCHLD:
				// ignore
			default:
				ed.addTip("ignored signal %s", sig)
			}
		case err := <-ed.reader.ErrorChan():
			ed.notify("reader error: %s", err.Error())
		case mouse := <-ed.reader.MouseChan():
			ed.addTip("mouse: %+v", mouse)
		case <-ed.reader.CPRChan():
			// Ignore CPR
		case k := <-ed.reader.KeyChan():
		lookupKey:
			keyBinding, ok := keyBindings[ed.mode]
			if !ok {
				ed.addTip("No binding for current mode")
				continue
			}

			fn, bound := keyBinding[k]
			if !bound {
				fn = keyBinding[Default]
			}

			ed.lastKey = k
			fn.Call(ed)
			act := ed.nextAction
			ed.nextAction = action{}

			switch act.actionType {
			case noAction:
				continue
			case reprocessKey:
				err = ed.refresh(false)
				if err != nil {
					return LineRead{Err: err}
				}
				goto lookupKey
			case exitReadLine:
				lr = act.returnValue
				if lr.EOF == false && lr.Err == nil && lr.Line != "" {
					ed.appendHistory(lr.Line)
				}

				return lr
			}
		}
	}
}
<commit_msg>Disable mouse tracking for now.<commit_after>// Package edit implements a command line editor.
package edit

import (
	"fmt"
	"os"
	"syscall"

	"github.com/elves/elvish/errutil"
	"github.com/elves/elvish/eval"
	"github.com/elves/elvish/logutil"
	"github.com/elves/elvish/parse"
	"github.com/elves/elvish/store"
	"github.com/elves/elvish/sys"
)

var Logger = logutil.GetLogger("[edit] ")

const (
	lackEOLRune = '\u23ce'
	lackEOL     = "\033[7m" + string(lackEOLRune) + "\033[m"
)

// Editor keeps the status of the line editor.
type Editor struct {
	file   *os.File
	writer *writer
	reader *Reader
	sigs   chan os.Signal
	store  *store.Store
	evaler *eval.Evaler
	cmdSeq int
	editorState
}

type editorState struct {
	// States used during ReadLine. Reset at the beginning of ReadLine.
	active                bool
	savedTermios          *sys.Termios
	tokens                []Token
	prompt, rprompt, line string
	dot                   int
	notifications         []string
	tips                  []string
	mode                  bufferMode
	completion            *completion
	completionLines       int
	navigation            *navigation
	history               historyState
	historyListing        *historyListing
	isExternal            map[string]bool
	// Used for builtins.
	lastKey    Key
	nextAction action
}

type bufferMode int

const (
	modeInsert bufferMode = iota
	modeCommand
	modeCompletion
	modeNavigation
	modeHistory
	modeHistoryListing
)

type actionType int

const (
	noAction actionType = iota
	reprocessKey
	exitReadLine
)

// LineRead is the result of ReadLine. Exactly one member is non-zero, making
// it effectively a tagged union.
type LineRead struct {
	Line string
	EOF  bool
	Err  error
}

// NewEditor creates an Editor.
func NewEditor(file *os.File, sigs chan os.Signal, ev *eval.Evaler, st *store.Store) *Editor {
	seq := -1
	if st != nil {
		var err error
		seq, err = st.NextCmdSeq()
		if err != nil {
			// TODO(xiaq): Also report the error
			seq = -1
		}
	}

	ed := &Editor{
		file:   file,
		writer: newWriter(file),
		reader: NewReader(file),
		sigs:   sigs,
		store:  st,
		evaler: ev,
		cmdSeq: seq,
	}
	ev.AddModule("le", makeModule(ed))
	return ed
}

func (ed *Editor) flash() {
	// TODO implement fish-like flash effect
}

func (ed *Editor) addTip(format string, args ...interface{}) {
	ed.tips = append(ed.tips, fmt.Sprintf(format, args...))
}

func (ed *Editor) notify(format string, args ...interface{}) {
	ed.notifications = append(ed.notifications, fmt.Sprintf(format, args...))
}

func (ed *Editor) refresh(fullRefresh bool) error {
	// Re-lex the line, unless we are in modeCompletion
	name := "[interacitve]"
	src := ed.line
	if ed.mode != modeCompletion {
		n, _ /*err*/ := parse.Parse(src)
		if n == nil {
			ed.tokens = []Token{{ParserError, src, nil, ""}}
		} else {
			ed.tokens = tokenize(src, n)
			_, err := ed.evaler.Compile(name, src, n)
			if err != nil {
				if err, ok := err.(*errutil.ContextualError); ok {
					ed.addTip("compiler error highlighted")
					p := err.Pos()
					for i, token := range ed.tokens {
						if token.Node.Begin() <= p && p < token.Node.End() {
							ed.tokens[i].MoreStyle += styleForCompilerError
							break
						}
					}
				}
			}
		}
		for i, t := range ed.tokens {
			for _, stylist := range stylists {
				ed.tokens[i].MoreStyle += stylist(t.Node, ed)
			}
		}
	}
	return ed.writer.refresh(&ed.editorState, fullRefresh)
}

// acceptCompletion accepts currently selected completion candidate.
func (ed *Editor) acceptCompletion() {
	c := ed.completion
	if 0 <= c.current && c.current < len(c.candidates) {
		accepted := c.candidates[c.current].source.text
		ed.insertAtDot(accepted)
	}
	ed.completion = nil
	ed.mode = modeInsert
}

// insertAtDot inserts text at the dot and moves the dot after it.
func (ed *Editor) insertAtDot(text string) {
	ed.line = ed.line[:ed.dot] + text + ed.line[ed.dot:]
	ed.dot += len(text)
}

func setupTerminal(file *os.File) (*sys.Termios, error) {
	fd := int(file.Fd())
	term, err := sys.NewTermiosFromFd(fd)
	if err != nil {
		return nil, fmt.Errorf("can't get terminal attribute: %s", err)
	}

	savedTermios := term.Copy()

	term.SetICanon(false)
	term.SetEcho(false)
	term.SetVMin(1)
	term.SetVTime(0)

	err = term.ApplyToFd(fd)
	if err != nil {
		return nil, fmt.Errorf("can't set up terminal attribute: %s", err)
	}

	/*
		err = sys.FlushInput(fd)
		if err != nil {
			return nil, fmt.Errorf("can't flush input: %s", err)
		}
	*/

	return savedTermios, nil
}

// startReadLine prepares the terminal for the editor.
func (ed *Editor) startReadLine() error {
	savedTermios, err := setupTerminal(ed.file)
	if err != nil {
		return err
	}
	ed.savedTermios = savedTermios

	_, width := sys.GetWinsize(int(ed.file.Fd()))
	// Turn on autowrap, write lackEOL along with enough padding to fill the
	// whole screen. If the cursor was in the first column, we end up in the
	// same line (just off the line boundary); otherwise we are now in the next
	// line. We now rewind to the first column and erase anything there. The
	// final effect is that a lackEOL gets written if and only if the cursor
	// was not in the first column.
	fmt.Fprintf(ed.file, "\033[?7h%s%*s\r \r", lackEOL, width-WcWidth(lackEOLRune), "")

	// Turn off autowrap. The edito has its own wrapping mechanism. Doing
	// wrapping manually means that when the actual width of some characters
	// are greater than what our wcwidth implementation tells us, characters at
	// the end of that line gets hidden -- compared to pushed to the next line,
	// which is more disastrous.
	ed.file.WriteString("\033[?7l")
	// Turn on SGR-style mouse tracking.
	//ed.file.WriteString("\033[?1000;1006h")
	return nil
}

// finishReadLine puts the terminal in a state suitable for other programs to
// use.
func (ed *Editor) finishReadLine(addError func(error)) {
	ed.mode = modeInsert
	ed.tips = nil
	ed.completion = nil
	ed.navigation = nil
	ed.dot = len(ed.line)
	// TODO Perhaps make it optional to NOT clear the rprompt
	ed.rprompt = ""
	addError(ed.refresh(false))
	ed.file.WriteString("\n")

	// ed.reader.Stop()
	ed.reader.Quit()

	// Turn on autowrap.
	ed.file.WriteString("\033[?7h")
	// Turn off mouse tracking.
	//ed.file.WriteString("\033[?1000;1006l")

	// restore termios
	err := ed.savedTermios.ApplyToFd(int(ed.file.Fd()))

	if err != nil {
		addError(fmt.Errorf("can't restore terminal attribute: %s", err))
	}
	ed.savedTermios = nil
	ed.editorState = editorState{}
}

// ReadLine reads a line interactively.
func (ed *Editor) ReadLine(prompt, rprompt func() string) (lr LineRead) {
	ed.editorState = editorState{active: true}
	isExternalCh := make(chan map[string]bool, 1)
	go getIsExternal(ed.evaler, isExternalCh)

	ed.writer.resetOldBuf()
	go ed.reader.Run()

	err := ed.startReadLine()
	if err != nil {
		return LineRead{Err: err}
	}
	defer ed.finishReadLine(func(err error) {
		if err != nil {
			lr.Err = errutil.CatError(lr.Err, err)
		}
	})

MainLoop:
	for {
		ed.prompt = prompt()
		ed.rprompt = rprompt()

		err := ed.refresh(false)
		if err != nil {
			return LineRead{Err: err}
		}

		ed.tips = nil

		select {
		case m := <-isExternalCh:
			ed.isExternal = m
		case sig := <-ed.sigs:
			// TODO(xiaq): Maybe support customizable handling of signals
			switch sig {
			case syscall.SIGINT:
				// Start over
				ed.editorState = editorState{
					savedTermios: ed.savedTermios,
					isExternal:   ed.isExternal,
				}
				goto MainLoop
			case syscall.SIGWINCH:
				continue MainLoop
			case syscall.SIGCHLD:
				// ignore
			default:
				ed.addTip("ignored signal %s", sig)
			}
		case err := <-ed.reader.ErrorChan():
			ed.notify("reader error: %s", err.Error())
		case mouse := <-ed.reader.MouseChan():
			ed.addTip("mouse: %+v", mouse)
		case <-ed.reader.CPRChan():
			// Ignore CPR
		case k := <-ed.reader.KeyChan():
		lookupKey:
			keyBinding, ok := keyBindings[ed.mode]
			if !ok {
				ed.addTip("No binding for current mode")
				continue
			}

			fn, bound := keyBinding[k]
			if !bound {
				fn = keyBinding[Default]
			}

			ed.lastKey = k
			fn.Call(ed)
			act := ed.nextAction
			ed.nextAction = action{}

			switch act.actionType {
			case noAction:
				continue
			case reprocessKey:
				err = ed.refresh(false)
				if err != nil {
					return LineRead{Err: err}
				}
				goto lookupKey
			case exitReadLine:
				lr = act.returnValue
				if lr.EOF == false && lr.Err == nil && lr.Line != "" {
					ed.appendHistory(lr.Line)
				}

				return lr
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

import "io/ioutil"

func WriteFile(fileName string, data []byte) error {
	return ioutil.WriteFile(fileName, data, 0644)
}

func ReadFile(fileName string) ([]byte, error) {
	return ioutil.ReadFile(fileName)
}
<commit_msg>Updated the WriteFile helper to create directories if needed to write the file in hoverctl<commit_after>package main

import (
	"io/ioutil"
	"os"
	"path"

	log "github.com/Sirupsen/logrus"
)

func WriteFile(filePath string, data []byte) error {
	basePath := path.Dir(filePath)
	fileName := path.Base(filePath)
	log.Debug(basePath)

	err := os.MkdirAll(basePath, 0777)
	if err != nil {
		return err
	}
	log.Debug("Should be writing?")
	return ioutil.WriteFile(basePath+"/"+fileName, data, 0644)
}

func ReadFile(filePath string) ([]byte, error) {
	return ioutil.ReadFile(filePath)
}
<|endoftext|>


<commit_before>package html

import (
	"golang.org/x/net/html"
	"golang.org/x/net/html/atom"
	"errors"
	"github.com/slyrz/newscat/util"
	"io"
	"unicode"
)

// Errors returned during Document parsing.
var (
	ErrNoHTML = errors.New("missing html element")
	ErrNoHead = errors.New("missing head element")
	ErrNoBody = errors.New("missing body element")
)

// Document is a parsed HTML document that extracts the document title and
// holds unexported pointers to the html, head and body nodes.
type Document struct {
	Title  *util.Text // the <title>...</title> text.
	Chunks []*Chunk   // all chunks found in this document.

	// Unexported fields.
	html *html.Node // the ... part
	head *html.Node // the ... part
	body *html.Node // the ... part

	// State variables used during parsing.
	ancestors int                // bitmask to track specific ancestor types
	linkText  map[*html.Node]int // length of text inside  tags
	normText  map[*html.Node]int // length of text outside  tags
}

// NewDocument parses the HTML data provided through an io.Reader interface.
func NewDocument(r io.Reader) (*Document, error) {
	root, err := html.Parse(r)
	if err != nil {
		return nil, err
	}

	doc := &Document{
		Title:    util.NewText(),
		Chunks:   make([]*Chunk, 0, 512),
		linkText: make(map[*html.Node]int),
		normText: make(map[*html.Node]int),
	}

	// Assign the fields html, head and body from the HTML page.
	iterateNode(root, func(n *html.Node) int {
		switch n.DataAtom {
		case atom.Html:
			doc.html = n
			return IterNext
		case atom.Body:
			doc.body = n
			return IterSkip
		case atom.Head:
			doc.head = n
			return IterSkip
		}
		// Keep going as long as we're missing some nodes.
		return IterNext
	})

	switch {
	case doc.html == nil:
		return nil, ErrNoHTML
	case doc.head == nil:
		return nil, ErrNoHead
	case doc.body == nil:
		return nil, ErrNoBody
	}

	// Detect the document title: First check if the document provides
	// Open Graph metadata; if so, use the metadata rather than the
	// value of the title element, because the metadata tends to be a tad
	// cleaner.
	title := ""
	iterateNode(doc.head, func(n *html.Node) int {
		if n.Type == html.ElementNode && n.DataAtom == atom.Meta {
			prop, content := "", ""
			for _, attr := range n.Attr {
				switch attr.Key {
				case "property":
					prop = attr.Val
				case "content":
					content = attr.Val
				}
			}
			if prop == "og:title" && content != "" {
				title = content
				return IterStop
			}
		}
		return IterNext
	})
	if title != "" {
		doc.Title.WriteString(title)
	} else {
		iterateNode(doc.head, func(n *html.Node) int {
			if n.Type == html.ElementNode && n.DataAtom == atom.Title {
				iterateText(n, doc.Title.WriteString)
				return IterStop
			}
			return IterNext
		})
	}

	doc.cleanBody(doc.body, 0)
	doc.countText(doc.body, false)
	doc.parseBody(doc.body)

	// Now we link the chunks.
	min, max := 0, len(doc.Chunks)-1
	for i := range doc.Chunks {
		if i > min {
			doc.Chunks[i].Prev = doc.Chunks[i-1]
		}
		if i < max {
			doc.Chunks[i].Next = doc.Chunks[i+1]
		}
	}
	return doc, nil
}

const (
	// We remember a few special node types when descending into their
	// children.
	AncestorArticle = 1 << iota
	AncestorAside
	AncestorBlockquote
	AncestorList
)

// countText counts the text inside of links and the text outside of links
// per html.Node. Counting is done cumulative, so the numbers of a parent node
// include the numbers of its child nodes.
func (doc *Document) countText(n *html.Node, insideLink bool) (linkText int, normText int) {
	linkText = 0
	normText = 0
	if n.Type == html.ElementNode && n.DataAtom == atom.A {
		insideLink = true
	}
	for s := n.FirstChild; s != nil; s = s.NextSibling {
		linkTextChild, normTextChild := doc.countText(s, insideLink)
		linkText += linkTextChild
		normText += normTextChild
	}
	if n.Type == html.TextNode {
		count := 0
		for _, rune := range n.Data {
			if unicode.IsLetter(rune) {
				count += 1
			}
		}
		if insideLink {
			linkText += count
		} else {
			normText += count
		}
	}
	doc.linkText[n] = linkText
	doc.normText[n] = normText
	return
}

var removeElements = map[atom.Atom]bool{
	atom.Address:    true,
	atom.Audio:      true,
	atom.Button:     true,
	atom.Canvas:     true,
	atom.Caption:    true,
	atom.Fieldset:   true,
	atom.Figcaption: true,
	atom.Figure:     true,
	atom.Footer:     true,
	atom.Form:       true,
	atom.Frame:      true,
	atom.Iframe:     true,
	atom.Map:        true,
	atom.Menu:       true,
	atom.Nav:        true,
	atom.Noscript:   true,
	atom.Object:     true,
	atom.Option:     true,
	atom.Output:     true,
	atom.Script:     true,
	atom.Select:     true,
	atom.Style:      true,
	atom.Svg:        true,
	atom.Textarea:   true,
	atom.Video:      true,
}

// cleanBody removes unwanted HTML elements from the HTML body.
func (doc *Document) cleanBody(n *html.Node, level int) {
	// removeNode returns true if a node should be removed from HTML document.
	removeNode := func(c *html.Node, level int) bool {
		if c.DataAtom == atom.Table {
			return level > 5
		}
		return removeElements[c.DataAtom]
	}

	var curr *html.Node = n.FirstChild
	var next *html.Node = nil
	for ; curr != nil; curr = next {
		// We have to remember the next sibling here because calling RemoveChild
		// sets curr's NextSibling pointer to nil and we would quit the loop
		// prematurely.
		next = curr.NextSibling
		if curr.Type == html.ElementNode {
			if removeNode(curr, level) {
				n.RemoveChild(curr)
			} else {
				doc.cleanBody(curr, level+1)
			}
		}
	}
}

var (
	ignoreNames = util.NewRegexFromWords(
		"breadcrumb",
		"byline",
		"caption",
		"comment",
		"community",
		"credit",
		"description",
		"email",
		"footer",
		"gallery",
		"hide",
		"infotext",
		"photo",
		"related",
		"shares",
		"social",
		"story[-_]?bar",
		"story[-_]?feature",
	)
	ignoreStyle = util.NewRegex(`(?i)display:\s*none`)
)

// parseBody parses the ... part of the HTML page. It creates
// Chunks for every html.TextNode found in the body.
func (doc *Document) parseBody(n *html.Node) {
	switch n.Type {
	case html.ElementNode:
		// We ignore the node if it has some nasty classes/ids/itemprops or if
		// its style attribute contains "display: none".
		for _, attr := range n.Attr {
			switch attr.Key {
			case "id", "class", "itemprop":
				if ignoreNames.In(attr.Val) {
					return
				}
			case "style":
				if ignoreStyle.In(attr.Val) {
					return
				}
			}
		}
		ancestorMask := 0
		switch n.DataAtom {
		// We convert headings and links to text immediately. This is easier
		// and feasible because headings and links don't contain many children.
		// Descending into these children and handling every TextNode separately
		// would make things unnecessary complicated and our results noisy.
		case atom.H1, atom.H2, atom.H3, atom.H4, atom.H5, atom.H6, atom.A:
			if chunk, err := NewChunk(doc, n); err == nil {
				doc.Chunks = append(doc.Chunks, chunk)
			}
			return
		// Now mask the element type, but only if it isn't already set.
		// If we mask a bit which was already set by one of our callers, we'd also
		// clear it at the end of this function, though it actually should be cleared
		// by the caller.
		case atom.Article:
			ancestorMask = AncestorArticle &^ doc.ancestors
		case atom.Aside:
			ancestorMask = AncestorAside &^ doc.ancestors
		case atom.Blockquote:
			ancestorMask = AncestorBlockquote &^ doc.ancestors
		case atom.Ul, atom.Ol:
			ancestorMask = AncestorList &^ doc.ancestors
		}
		// Add our mask to the ancestor bitmask.
		doc.ancestors |= ancestorMask
		for c := n.FirstChild; c != nil; c = c.NextSibling {
			doc.parseBody(c)
		}
		// Remove our mask from the ancestor bitmask.
		doc.ancestors &^= ancestorMask
	case html.TextNode:
		if chunk, err := NewChunk(doc, n); err == nil {
			doc.Chunks = append(doc.Chunks, chunk)
		}
	}
}

// TextStat contains the number of words and sentences found in text.
type TextStat struct {
	Words     int // total number of words
	Sentences int // total number of sentences
	Count     int // number of texts used to calculate this stats
}

// GetClassStats groups the document chunks by their classes (defined by the
// class attribute of HTML nodes) and calculates TextStats for each class.
func (doc *Document) GetClassStats() map[string]*TextStat {
	result := make(map[string]*TextStat)
	for _, chunk := range doc.Chunks {
		for _, class := range chunk.Classes {
			if stat, ok := result[class]; ok {
				stat.Words += chunk.Text.Words
				stat.Sentences += chunk.Text.Sentences
				stat.Count += 1
			} else {
				result[class] = &TextStat{chunk.Text.Words, chunk.Text.Sentences, 1}
			}
		}
	}
	return result
}

// GetClusterStats groups the document chunks by common ancestors and
// calculates TextStats for each group of chunks.
func (doc *Document) GetClusterStats() map[*Chunk]*TextStat {
	// Don't ascend further than this.
	const maxAncestors = 3

	// Count TextStats for Chunk ancestors.
	ancestorStat := make(map[*html.Node]*TextStat)
	for _, chunk := range doc.Chunks {
		node, count := chunk.Block, 0
		for node != nil && count < maxAncestors {
			if stat, ok := ancestorStat[node]; ok {
				stat.Words += chunk.Text.Words
				stat.Sentences += chunk.Text.Sentences
				stat.Count += 1
			} else {
				ancestorStat[node] = &TextStat{chunk.Text.Words, chunk.Text.Sentences, 1}
			}
			node, count = node.Parent, count+1
		}
	}

	// Generate result. For each chunk pick the best TextStats from its ancestors.
	result := make(map[*Chunk]*TextStat)
	for _, chunk := range doc.Chunks {
		node := chunk.Block
		if node == nil {
			continue
		}
		// Start with the parent's TextStat. Then ascend and check if the
		// current chunk has an ancestor with better stats. Use the best stat
		// as result.
		stat := ancestorStat[node]
		for {
			if node = node.Parent; node == nil {
				break
			}
			if statPrev, ok := ancestorStat[node]; ok {
				if stat.Count < statPrev.Count {
					stat = statPrev
				}
			} else {
				break
			}
		}
		result[chunk] = stat
	}
	return result
}
<commit_msg>allow tables and forms everywhere<commit_after>package html

import (
	"errors"
	"github.com/slyrz/newscat/util"
	"golang.org/x/net/html"
	"golang.org/x/net/html/atom"
	"io"
	"unicode"
)

// Errors returned during Document parsing.
var (
	ErrNoHTML = errors.New("missing html element")
	ErrNoHead = errors.New("missing head element")
	ErrNoBody = errors.New("missing body element")
)

// Document is a parsed HTML document that extracts the document title and
// holds unexported pointers to the html, head and body nodes.
type Document struct {
	Title  *util.Text // the <title>...</title> text.
	Chunks []*Chunk   // all chunks found in this document.

	// Unexported fields.
	html *html.Node // the ... part
	head *html.Node // the ... part
	body *html.Node // the ... part

	// State variables used during parsing.
	ancestors int                // bitmask to track specific ancestor types
	linkText  map[*html.Node]int // length of text inside  tags
	normText  map[*html.Node]int // length of text outside  tags
}

// NewDocument parses the HTML data provided through an io.Reader interface.
func NewDocument(r io.Reader) (*Document, error) {
	root, err := html.Parse(r)
	if err != nil {
		return nil, err
	}

	doc := &Document{
		Title:    util.NewText(),
		Chunks:   make([]*Chunk, 0, 512),
		linkText: make(map[*html.Node]int),
		normText: make(map[*html.Node]int),
	}

	// Assign the fields html, head and body from the HTML page.
	iterateNode(root, func(n *html.Node) int {
		switch n.DataAtom {
		case atom.Html:
			doc.html = n
			return IterNext
		case atom.Body:
			doc.body = n
			return IterSkip
		case atom.Head:
			doc.head = n
			return IterSkip
		}
		// Keep going as long as we're missing some nodes.
		return IterNext
	})

	switch {
	case doc.html == nil:
		return nil, ErrNoHTML
	case doc.head == nil:
		return nil, ErrNoHead
	case doc.body == nil:
		return nil, ErrNoBody
	}

	// Detect the document title: First check if the document provides
	// Open Graph metadata; if so, use the metadata rather than the
	// value of the title element, because the metadata tends to be a tad
	// cleaner.
	title := ""
	iterateNode(doc.head, func(n *html.Node) int {
		if n.Type == html.ElementNode && n.DataAtom == atom.Meta {
			prop, content := "", ""
			for _, attr := range n.Attr {
				switch attr.Key {
				case "property":
					prop = attr.Val
				case "content":
					content = attr.Val
				}
			}
			if prop == "og:title" && content != "" {
				title = content
				return IterStop
			}
		}
		return IterNext
	})
	if title != "" {
		doc.Title.WriteString(title)
	} else {
		iterateNode(doc.head, func(n *html.Node) int {
			if n.Type == html.ElementNode && n.DataAtom == atom.Title {
				iterateText(n, doc.Title.WriteString)
				return IterStop
			}
			return IterNext
		})
	}

	doc.cleanBody(doc.body, 0)
	doc.countText(doc.body, false)
	doc.parseBody(doc.body)

	// Now we link the chunks.
	min, max := 0, len(doc.Chunks)-1
	for i := range doc.Chunks {
		if i > min {
			doc.Chunks[i].Prev = doc.Chunks[i-1]
		}
		if i < max {
			doc.Chunks[i].Next = doc.Chunks[i+1]
		}
	}
	return doc, nil
}

const (
	// We remember a few special node types when descending into their
	// children.
	AncestorArticle = 1 << iota
	AncestorAside
	AncestorBlockquote
	AncestorList
)

// countText counts the text inside of links and the text outside of links
// per html.Node. Counting is done cumulative, so the numbers of a parent node
// include the numbers of its child nodes.
func (doc *Document) countText(n *html.Node, insideLink bool) (linkText int, normText int) {
	linkText = 0
	normText = 0
	if n.Type == html.ElementNode && n.DataAtom == atom.A {
		insideLink = true
	}
	for s := n.FirstChild; s != nil; s = s.NextSibling {
		linkTextChild, normTextChild := doc.countText(s, insideLink)
		linkText += linkTextChild
		normText += normTextChild
	}
	if n.Type == html.TextNode {
		count := 0
		for _, rune := range n.Data {
			if unicode.IsLetter(rune) {
				count += 1
			}
		}
		if insideLink {
			linkText += count
		} else {
			normText += count
		}
	}
	doc.linkText[n] = linkText
	doc.normText[n] = normText
	return
}

var removeElements = map[atom.Atom]bool{
	atom.Address:    true,
	atom.Audio:      true,
	atom.Button:     true,
	atom.Canvas:     true,
	atom.Caption:    true,
	atom.Fieldset:   true,
	atom.Figcaption: true,
	atom.Figure:     true,
	atom.Footer:     true,
	atom.Frame:      true,
	atom.Iframe:     true,
	atom.Map:        true,
	atom.Menu:       true,
	atom.Nav:        true,
	atom.Noscript:   true,
	atom.Object:     true,
	atom.Option:     true,
	atom.Output:     true,
	atom.Script:     true,
	atom.Select:     true,
	atom.Style:      true,
	atom.Svg:        true,
	atom.Textarea:   true,
	atom.Video:      true,
}

// cleanBody removes unwanted HTML elements from the HTML body.
func (doc *Document) cleanBody(n *html.Node, level int) {
	// removeNode returns true if a node should be removed from HTML document.
	removeNode := func(c *html.Node, level int) bool {
		return removeElements[c.DataAtom]
	}

	var curr *html.Node = n.FirstChild
	var next *html.Node = nil
	for ; curr != nil; curr = next {
		// We have to remember the next sibling here because calling RemoveChild
		// sets curr's NextSibling pointer to nil and we would quit the loop
		// prematurely.
		next = curr.NextSibling
		if curr.Type == html.ElementNode {
			if removeNode(curr, level) {
				n.RemoveChild(curr)
			} else {
				doc.cleanBody(curr, level+1)
			}
		}
	}
}

var (
	ignoreNames = util.NewRegexFromWords(
		"breadcrumb",
		"byline",
		"caption",
		"comment",
		"community",
		"credit",
		"description",
		"email",
		"footer",
		"gallery",
		"hide",
		"infotext",
		"photo",
		"related",
		"shares",
		"social",
		"story[-_]?bar",
		"story[-_]?feature",
	)
	ignoreStyle = util.NewRegex(`(?i)display:\s*none`)
)

// parseBody parses the ... part of the HTML page. It creates
// Chunks for every html.TextNode found in the body.
func (doc *Document) parseBody(n *html.Node) {
	switch n.Type {
	case html.ElementNode:
		// We ignore the node if it has some nasty classes/ids/itemprops or if
		// its style attribute contains "display: none".
		for _, attr := range n.Attr {
			switch attr.Key {
			case "id", "class", "itemprop":
				if ignoreNames.In(attr.Val) {
					return
				}
			case "style":
				if ignoreStyle.In(attr.Val) {
					return
				}
			}
		}
		ancestorMask := 0
		switch n.DataAtom {
		// We convert headings and links to text immediately. This is easier
		// and feasible because headings and links don't contain many children.
		// Descending into these children and handling every TextNode separately
		// would make things unnecessary complicated and our results noisy.
		case atom.H1, atom.H2, atom.H3, atom.H4, atom.H5, atom.H6, atom.A:
			if chunk, err := NewChunk(doc, n); err == nil {
				doc.Chunks = append(doc.Chunks, chunk)
			}
			return
		// Now mask the element type, but only if it isn't already set.
		// If we mask a bit which was already set by one of our callers, we'd also
		// clear it at the end of this function, though it actually should be cleared
		// by the caller.
		case atom.Article:
			ancestorMask = AncestorArticle &^ doc.ancestors
		case atom.Aside:
			ancestorMask = AncestorAside &^ doc.ancestors
		case atom.Blockquote:
			ancestorMask = AncestorBlockquote &^ doc.ancestors
		case atom.Ul, atom.Ol:
			ancestorMask = AncestorList &^ doc.ancestors
		}
		// Add our mask to the ancestor bitmask.
		doc.ancestors |= ancestorMask
		for c := n.FirstChild; c != nil; c = c.NextSibling {
			doc.parseBody(c)
		}
		// Remove our mask from the ancestor bitmask.
		doc.ancestors &^= ancestorMask
	case html.TextNode:
		if chunk, err := NewChunk(doc, n); err == nil {
			doc.Chunks = append(doc.Chunks, chunk)
		}
	}
}

// TextStat contains the number of words and sentences found in text.
type TextStat struct {
	Words     int // total number of words
	Sentences int // total number of sentences
	Count     int // number of texts used to calculate this stats
}

// GetClassStats groups the document chunks by their classes (defined by the
// class attribute of HTML nodes) and calculates TextStats for each class.
func (doc *Document) GetClassStats() map[string]*TextStat {
	result := make(map[string]*TextStat)
	for _, chunk := range doc.Chunks {
		for _, class := range chunk.Classes {
			if stat, ok := result[class]; ok {
				stat.Words += chunk.Text.Words
				stat.Sentences += chunk.Text.Sentences
				stat.Count += 1
			} else {
				result[class] = &TextStat{chunk.Text.Words, chunk.Text.Sentences, 1}
			}
		}
	}
	return result
}

// GetClusterStats groups the document chunks by common ancestors and
// calculates TextStats for each group of chunks.
func (doc *Document) GetClusterStats() map[*Chunk]*TextStat {
	// Don't ascend further than this.
	const maxAncestors = 3

	// Count TextStats for Chunk ancestors.
	ancestorStat := make(map[*html.Node]*TextStat)
	for _, chunk := range doc.Chunks {
		node, count := chunk.Block, 0
		for node != nil && count < maxAncestors {
			if stat, ok := ancestorStat[node]; ok {
				stat.Words += chunk.Text.Words
				stat.Sentences += chunk.Text.Sentences
				stat.Count += 1
			} else {
				ancestorStat[node] = &TextStat{chunk.Text.Words, chunk.Text.Sentences, 1}
			}
			node, count = node.Parent, count+1
		}
	}

	// Generate result. For each chunk pick the best TextStats from its ancestors.
	result := make(map[*Chunk]*TextStat)
	for _, chunk := range doc.Chunks {
		node := chunk.Block
		if node == nil {
			continue
		}
		// Start with the parent's TextStat. Then ascend and check if the
		// current chunk has an ancestor with better stats. Use the best stat
		// as result.
		stat := ancestorStat[node]
		for {
			if node = node.Parent; node == nil {
				break
			}
			if statPrev, ok := ancestorStat[node]; ok {
				if stat.Count < statPrev.Count {
					stat = statPrev
				}
			} else {
				break
			}
		}
		result[chunk] = stat
	}
	return result
}
<|endoftext|>


<commit_before>package emailmodels

import (
	"errors"
	"fmt"
	"socialapi/models"

	"github.com/sendgrid/sendgrid-go"
)

type Mailer struct {
	UserContact   *UserContact
	Body          string
	Subject       string
	EmailSettings *EmailSettings
	Information   string
}

func NewMailer(a *models.Account, es *EmailSettings) (*Mailer, error) {
	// Fetch user contact
	uc, err := FetchUserContactWithToken(a.Id)
	if err != nil {
		return nil, err
	}

	return &Mailer{
		UserContact:   uc,
		EmailSettings: es,
	}, nil
}

func (m *Mailer) SendMail(contentType, body, subject string) error {
	m.Body = body
	m.Subject = subject

	if err := m.validateMailer(); err != nil {
		return err
	}

	if err := m.UserContact.GenerateToken(contentType); err != nil {
		return err
	}

	content, err := m.prepareContentWithLayout(contentType)
	if err != nil {
		return err
	}

	m.Body = content

	sg := sendgrid.NewSendGridClient(m.EmailSettings.Username, m.EmailSettings.Password)
	fullname := fmt.Sprintf("%s %s", m.UserContact.FirstName, m.UserContact.LastName)

	message := sendgrid.NewMail()
	message.AddTo(m.getRecipient())
	message.AddToName(fullname)
	message.SetSubject(m.Subject)
	message.SetHTML(m.Body)
	message.SetFrom(m.EmailSettings.DefaultFromMail)
	message.SetFromName(m.EmailSettings.DefaultFromName)

	if err := sg.Send(message); err != nil {
		return fmt.Errorf("an error occurred while sending notification email to %s: %s", m.UserContact.Username, err)
	}

	return nil
}

func (m *Mailer) prepareContentWithLayout(contentType string) (string, error) {
	lc := NewLayoutContent(m.UserContact, contentType, m.Body)
	lc.Information = m.Information

	return lc.Render()
}

func (m *Mailer) getRecipient() string {
	if m.EmailSettings.ForcedRecipient != "" {
		return m.EmailSettings.ForcedRecipient
	}

	return m.UserContact.Email
}

func (m *Mailer) validateMailer() error {
	if m.Body == "" {
		return errors.New("Mailer body is not set")
	}

	if m.Subject == "" {
		return errors.New("Mailer subject is not set")
	}

	if m.EmailSettings == nil {
		return errors.New("Mailer email settings is not set")
	}

	if m.UserContact == nil {
		return errors.New("User contact settings is not set")
	}

	return nil
}
<commit_msg>mailsender/refactoring: mailsender is centralized<commit_after>package emailmodels

import (
	"errors"
	"fmt"
	"socialapi/models"
	"socialapi/workers/email/sender"
)

// type Mailer struct {
// 	UserContact   *UserContact
// 	Body          string
// 	Subject       string
// 	EmailSettings *EmailSettings
// 	Information   string
// }

type Mailer struct {
	UserContact   *UserContact
	Mail          *sender.Mail
	EmailSettings *EmailSettings
	Information   string
}

// func NewMailer(a *models.Account, es *EmailSettings) (*Mailer, error) {
// 	// Fetch user contact
// 	uc, err := FetchUserContactWithToken(a.Id)
// 	if err != nil {
// 		return nil, err
// 	}

// 	return &Mailer{
// 		UserContact:   uc,
// 		EmailSettings: es,
// 	}, nil
// }

func NewMailer(a *models.Account, es *EmailSettings) (*Mailer, error) {
	// Fetch user contact
	uc, err := FetchUserContactWithToken(a.Id)
	if err != nil {
		return nil, err
	}

	return &Mailer{
		UserContact:   uc,
		EmailSettings: es,
	}, nil
}

func (m *Mailer) SendMail(contentType, body, subject string) error {
	m.Mail.Text = body
	m.Mail.Subject = subject

	if err := m.validateMailer(); err != nil {
		return err
	}

	if err := m.UserContact.GenerateToken(contentType); err != nil {
		return err
	}

	content, err := m.prepareContentWithLayout(contentType)
	if err != nil {
		return err
	}

	m.Mail.Text = content
	m.Mail.To = m.getRecipient()
	m.Mail.From = m.EmailSettings.DefaultFromMail
	m.Mail.FromName = m.EmailSettings.DefaultFromName

	if err := sender.Send(m.Mail); err != nil {
		return fmt.Errorf("an error occurred while sending notification email to %s: %s", m.UserContact.Username, err)
	}

	return nil

	// sg := sendgrid.NewSendGridClient(m.EmailSettings.Username, m.EmailSettings.Password)
	// fullname := fmt.Sprintf("%s %s", m.UserContact.FirstName, m.UserContact.LastName)

	// message := sendgrid.NewMail()
	// message.AddTo(m.getRecipient())
	// message.AddToName(fullname)
	// message.SetSubject(m.Subject)
	// message.SetHTML(m.Body)
	// message.SetFrom(m.EmailSettings.DefaultFromMail)
	// message.SetFromName(m.EmailSettings.DefaultFromName)

	// if err := sg.Send(message); err != nil {
	// 	return fmt.Errorf("an error occurred while sending notification email to %s: %s", m.UserContact.Username, err)
	// }

	// return nil
}

// func (m *Mailer) SendMail(contentType, body, subject string) error {
// 	m.Body = body
// 	m.Subject = subject

// 	if err := m.validateMailer(); err != nil {
// 		return err
// 	}

// 	if err := m.UserContact.GenerateToken(contentType); err != nil {
// 		return err
// 	}

// 	content, err := m.prepareContentWithLayout(contentType)
// 	if err != nil {
// 		return err
// 	}

// 	m.Body = content

// 	sg := sendgrid.NewSendGridClient(m.EmailSettings.Username, m.EmailSettings.Password)
// 	fullname := fmt.Sprintf("%s %s", m.UserContact.FirstName, m.UserContact.LastName)

// 	message := sendgrid.NewMail()
// 	message.AddTo(m.getRecipient())
// 	message.AddToName(fullname)
// 	message.SetSubject(m.Subject)
// 	message.SetHTML(m.Body)
// 	message.SetFrom(m.EmailSettings.DefaultFromMail)
// 	message.SetFromName(m.EmailSettings.DefaultFromName)

// 	if err := sg.Send(message); err != nil {
// 		return fmt.Errorf("an error occurred while sending notification email to %s: %s", m.UserContact.Username, err)
// 	}

// 	return nil
// }

func (m *Mailer) prepareContentWithLayout(contentType string) (string, error) {
	lc := NewLayoutContent(m.UserContact, contentType, m.Mail.Text)
	lc.Information = m.Information

	return lc.Render()
}

// func (m *Mailer) prepareContentWithLayout(contentType string) (string, error) {
// 	lc := NewLayoutContent(m.UserContact, contentType, m.Body)
// 	lc.Information = m.Information

// 	return lc.Render()
// }

func (m *Mailer) getRecipient() string {
	if m.EmailSettings.ForcedRecipient != "" {
		return m.EmailSettings.ForcedRecipient
	}

	return m.UserContact.Email
}

// func (m *Mailer) validateMailer() error {
// 	if m.Body == "" {
// 		return errors.New("Mailer body is not set")
// 	}

// 	if m.Subject == "" {
// 		return errors.New("Mailer subject is not set")
// 	}

// 	if m.EmailSettings == nil {
// 		return errors.New("Mailer email settings is not set")
// 	}

// 	if m.UserContact == nil {
// 		return errors.New("User contact settings is not set")
// 	}

// 	return nil
// }

func (m *Mailer) validateMailer() error {
	if m.Mail.Text == "" {
		return errors.New("Mailer body is not set")
	}

	if m.Mail.Subject == "" {
		return errors.New("Mailer subject is not set")
	}

	if m.EmailSettings == nil {
		return errors.New("Mailer email settings is not set")
	}

	if m.UserContact == nil {
		return errors.New("User contact settings is not set")
	}

	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/mg/i"
	"github.com/mg/i/igen"
	"math"
	"os"
)

type permute struct {
	items []rune
	n     int
	atEnd bool
}

func Permute(items []rune) i.Forward {
	return &permute{items: items, n: 1, atEnd: false}
}

func (p *permute) Error() error {
	return nil
}

func (p *permute) Value() interface{} {
	return p.items
}

func (p *permute) AtEnd() bool {
	return p.atEnd
}

func (per *permute) Next() error {
	var i int
	p := per.n
	for i = 1; i <= len(per.items) && math.Mod(float64(p), float64(i)) == 0; i++ {
		p /= i
	}
	d := int(math.Mod(float64(p), float64(i)))
	j := len(per.items) - i
	if j < 0 {
		per.atEnd = true
		return nil
	}

	copy(per.items[j+1:len(per.items)], reverse(per.items[j+1:len(per.items)]))
	per.items[j], per.items[j+d] = per.items[j+d], per.items[j]
	per.n++
	return nil
}

func reverse(in []rune) []rune {
	out := make([]rune, len(in))
	for i, v := range in {
		out[len(out)-i-1] = v
	}
	return out
}

func generate(from, to rune) []rune {
	list := make([]rune, 0, to-from+1)
	for itr := igen.Range(int(from), int(to)+1); !itr.AtEnd(); itr.Next() {
		list = append(list, rune(itr.Int()))
	}
	return list
}

func main() {
	if len(os.Args) != 3 {
		fmt.Printf("Usage %s FROM TO\n", os.Args[0])
		os.Exit(0)
	}
	from, to := rune(os.Args[1][0]), rune(os.Args[2][0])

	i.Each(
		Permute(generate(from, to)),
		func(itr i.Iterator) bool {
			r, _ := itr.Value().([]rune)
			fmt.Println(string(r))
			return true
		})
}
<commit_msg>permutations: add SetError()<commit_after>package main

import (
	"fmt"
	"github.com/mg/i"
	"github.com/mg/i/igen"
	"math"
	"os"
)

type permute struct {
	items []rune
	n     int
	atEnd bool
}

func Permute(items []rune) i.Forward {
	return &permute{items: items, n: 1, atEnd: false}
}

func (p *permute) Error() error {
	return nil
}

func (p *permute) SetError(err error) {
}

func (p *permute) Value() interface{} {
	return p.items
}

func (p *permute) AtEnd() bool {
	return p.atEnd
}

func (per *permute) Next() error {
	var i int
	p := per.n
	for i = 1; i <= len(per.items) && math.Mod(float64(p), float64(i)) == 0; i++ {
		p /= i
	}
	d := int(math.Mod(float64(p), float64(i)))
	j := len(per.items) - i
	if j < 0 {
		per.atEnd = true
		return nil
	}

	copy(per.items[j+1:len(per.items)], reverse(per.items[j+1:len(per.items)]))
	per.items[j], per.items[j+d] = per.items[j+d], per.items[j]
	per.n++
	return nil
}

func reverse(in []rune) []rune {
	out := make([]rune, len(in))
	for i, v := range in {
		out[len(out)-i-1] = v
	}
	return out
}

func generate(from, to rune) []rune {
	list := make([]rune, 0, to-from+1)
	for itr := igen.Range(int(from), int(to)+1); !itr.AtEnd(); itr.Next() {
		list = append(list, rune(itr.Int()))
	}
	return list
}

func main() {
	if len(os.Args) != 3 {
		fmt.Printf("Usage %s FROM TO\n", os.Args[0])
		os.Exit(0)
	}
	from, to := rune(os.Args[1][0]), rune(os.Args[2][0])

	i.Each(
		Permute(generate(from, to)),
		func(itr i.Iterator) bool {
			r, _ := itr.Value().([]rune)
			fmt.Println(string(r))
			return true
		})
}
<|endoftext|>


<commit_before>// Copyright 2013 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 cache

import (
	"encoding/gob"

	"github.com/jacobsa/gcloud/syncutil"
	"github.com/jacobsa/util/lrucache"
)

// Create a cache that holds the given number of items, evicting the least
// recently used item when more space is needed.
func NewLruCache(capacity uint) Cache {
	c := &lruCache{
		wrapped: lrucache.New(int(capacity)),
	}

	c.mu = syncutil.NewInvariantMutex(c.wrapped.CheckInvariants)
	return c
}

type lruCache struct {
	mu syncutil.InvariantMutex

	// GUARDED_BY(mu)
	wrapped lrucache.Cache
}

func (c *lruCache) Insert(key Key, value interface{}) {
	c.mu.Lock()
	defer c.mu.Unlock()

	c.wrapped.Insert(string(key[:]), value)
}

func (c *lruCache) LookUp(key Key) interface{} {
	c.mu.Lock()
	defer c.mu.Unlock()

	return c.wrapped.LookUp(string(key[:]))
}

////////////////////////////////////////////////////////////////////////
// Gob encoding
////////////////////////////////////////////////////////////////////////

func init() {
	// Make sure that lruCaches can be encoded where Cache interface variables
	// are expected.
	gob.Register(&lruCache{})
}

func (c *lruCache) GobEncode() (b []byte, err error) {
	// Simply encode the wrapped cache. Our tricky part is on the decode path.
	b, err = c.wrapped.GobEncode()
	return
}

func (c *lruCache) GobDecode(b []byte) (err error) {
	// Decode the wrapped cache.
	err = c.wrapped.GobDecode(b)
	if err != nil {
		return
	}

	// Initialize the mutex.
	c.mu = syncutil.NewInvariantMutex(c.wrapped.CheckInvariants)

	return
}
<commit_msg>Don't forget to lock when encoding.<commit_after>// Copyright 2013 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 cache

import (
	"encoding/gob"

	"github.com/jacobsa/gcloud/syncutil"
	"github.com/jacobsa/util/lrucache"
)

// Create a cache that holds the given number of items, evicting the least
// recently used item when more space is needed.
func NewLruCache(capacity uint) Cache {
	c := &lruCache{
		wrapped: lrucache.New(int(capacity)),
	}

	c.mu = syncutil.NewInvariantMutex(c.wrapped.CheckInvariants)
	return c
}

type lruCache struct {
	mu syncutil.InvariantMutex

	// GUARDED_BY(mu)
	wrapped lrucache.Cache
}

func (c *lruCache) Insert(key Key, value interface{}) {
	c.mu.Lock()
	defer c.mu.Unlock()

	c.wrapped.Insert(string(key[:]), value)
}

func (c *lruCache) LookUp(key Key) interface{} {
	c.mu.Lock()
	defer c.mu.Unlock()

	return c.wrapped.LookUp(string(key[:]))
}

////////////////////////////////////////////////////////////////////////
// Gob encoding
////////////////////////////////////////////////////////////////////////

func init() {
	// Make sure that lruCaches can be encoded where Cache interface variables
	// are expected.
	gob.Register(&lruCache{})
}

func (c *lruCache) GobEncode() (b []byte, err error) {
	c.mu.Lock()
	defer c.mu.Unlock()

	// Simply encode the wrapped cache. Our tricky part is on the decode path.
	b, err = c.wrapped.GobEncode()
	return
}

func (c *lruCache) GobDecode(b []byte) (err error) {
	// Decode the wrapped cache.
	err = c.wrapped.GobDecode(b)
	if err != nil {
		return
	}

	// Initialize the mutex.
	c.mu = syncutil.NewInvariantMutex(c.wrapped.CheckInvariants)

	return
}
<|endoftext|>


<commit_before>// Package email provides email sending via SMTP.
package email

import (
	"encoding/base64"
	"fmt"
	"net/smtp"
	"sync"
)

// *****************************************************************************
// Thread-Safe Configuration
// *****************************************************************************

var (
	info      Info
	infoMutex sync.RWMutex
)

// Info holds the details for the SMTP server.
type Info struct {
	Username string
	Password string
	Hostname string
	Port     int
	From     string
}

// SetConfig stores the config.
func SetConfig(i Info) {
	infoMutex.Lock()
	info = i
	infoMutex.Unlock()
}

// ResetConfig removes the config.
func ResetConfig() {
	infoMutex.Lock()
	info = Info{}
	infoMutex.Unlock()
}

// Config returns the config.
func Config() Info {
	infoMutex.RLock()
	defer infoMutex.RUnlock()
	return info
}

// Configuration defines the shared configuration interface.
type Configuration struct {
	Info
}

// Shared returns the global configuration information.
func Shared() Configuration {
	return Configuration{
		Config(),
	}
}

// *****************************************************************************
// Email Handling
// *****************************************************************************

// Send mails an email.
func (c Configuration) Send(to, subject, body string) error {
	auth := smtp.PlainAuth("", c.Username, c.Password, c.Hostname)

	// Create the header
	header := make(map[string]string)
	header["From"] = c.From
	header["To"] = to
	header["Subject"] = subject
	header["MIME-Version"] = "1.0"
	header["Content-Type"] = `text/plain; charset="utf-8"`
	header["Content-Transfer-Encoding"] = "base64"

	// Set the message
	message := ""
	for k, v := range header {
		message += fmt.Sprintf("%s: %s\r\n", k, v)
	}
	message += "\r\n" + base64.StdEncoding.EncodeToString([]byte(body))

	// Send the email
	err := smtp.SendMail(
		fmt.Sprintf("%s:%d", c.Hostname, c.Port),
		auth,
		c.From,
		[]string{to},
		[]byte(message),
	)

	return err
}
<commit_msg>Simplify email comment<commit_after>// Package email provides email sending via SMTP.
package email

import (
	"encoding/base64"
	"fmt"
	"net/smtp"
	"sync"
)

// *****************************************************************************
// Thread-Safe Configuration
// *****************************************************************************

var (
	info      Info
	infoMutex sync.RWMutex
)

// Info holds the details for the SMTP server.
type Info struct {
	Username string
	Password string
	Hostname string
	Port     int
	From     string
}

// SetConfig stores the config.
func SetConfig(i Info) {
	infoMutex.Lock()
	info = i
	infoMutex.Unlock()
}

// ResetConfig removes the config.
func ResetConfig() {
	infoMutex.Lock()
	info = Info{}
	infoMutex.Unlock()
}

// Config returns the config.
func Config() Info {
	infoMutex.RLock()
	defer infoMutex.RUnlock()
	return info
}

// Configuration defines the shared configuration interface.
type Configuration struct {
	Info
}

// Shared returns the global configuration information.
func Shared() Configuration {
	return Configuration{
		Config(),
	}
}

// *****************************************************************************
// Email Handling
// *****************************************************************************

// Send an email.
func (c Configuration) Send(to, subject, body string) error {
	auth := smtp.PlainAuth("", c.Username, c.Password, c.Hostname)

	// Create the header
	header := make(map[string]string)
	header["From"] = c.From
	header["To"] = to
	header["Subject"] = subject
	header["MIME-Version"] = "1.0"
	header["Content-Type"] = `text/plain; charset="utf-8"`
	header["Content-Transfer-Encoding"] = "base64"

	// Set the message
	message := ""
	for k, v := range header {
		message += fmt.Sprintf("%s: %s\r\n", k, v)
	}
	message += "\r\n" + base64.StdEncoding.EncodeToString([]byte(body))

	// Send the email
	err := smtp.SendMail(
		fmt.Sprintf("%s:%d", c.Hostname, c.Port),
		auth,
		c.From,
		[]string{to},
		[]byte(message),
	)

	return err
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"strconv"

	"github.com/hyperledger/fabric/core/chaincode/shim"
)

// SimpleChaincode basic struct
type SimpleChaincode struct {
}

func main() {
	fmt.Println("started logging in main()")
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("failed in function main(), error is %v", err)
	}
}

var projectName string
var projectRate int
var projectPeriod, projectGoal, projectTimes int
var projectBenfiary string
var projectState string
var currentPrice float64
var currentSummary int

//Init function
//Step1: 获得调用init()的caller, 并且保存在"admin"中
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Init()")

	//get caller's certificate, and saved to "admin" state
	fmt.Println("started get caller's metatdat")
	adminCert, err := stub.GetCallerCertificate()
	if err != nil {
		return nil, errors.New("failed getting metadata")
	}
	if len(adminCert) == 0 {
		return nil, errors.New("Invalid admin certificate. Empty.")
	}
	fmt.Printf("the administrator is [%v]", adminCert)
	stub.PutState("admin", adminCert)

	//started to initialize project
	fmt.Println("started to initialize project")
	if len(args) != 5 {
		return nil, errors.New("failed in args")
	}
	projectName = args[0]                    //项目名称
	projectRate, _ = strconv.Atoi(args[1])   //项目年化利率
	projectPeriod, _ = strconv.Atoi(args[2]) //项目天数
	projectGoal, _ = strconv.Atoi(args[3])   //项目目标募集金额
	projectTimes = 1                         //项目期数
	projectBenfiary = args[4]                //项目受益人
	projectState = "draft"                   //项目当前状态
	currentPrice = 1.0

	//started to initialize the table: Shares
	fmt.Println("started to create table: Shares")
	tableErr := stub.CreateTable("Shares", []*shim.ColumnDefinition{
		&shim.ColumnDefinition{Name: "User", Type: shim.ColumnDefinition_STRING, Key: true},
		&shim.ColumnDefinition{Name: "Amount", Type: shim.ColumnDefinition_INT64, Key: false},
	})
	if tableErr != nil {
		return nil, errors.New("Failed creating AssetsOnwership table.")
	}

	return nil, nil
}

// Invoke function
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Invoke()")

	switch function {
	case "goPublic":
		if len(args) != 0 {
			return nil, errors.New("failed in args")
		}
		fmt.Println("started logging in goPublic()")
		projectState = "public"
		return nil, nil //end of goPublic
	case "pay":
		if len(args) != 2 {
			return nil, errors.New("failed in args")
		}
		fmt.Println("started logging in pay()")
		user := args[0]
		amount := args[1]

		fmt.Println("step1: chechk whether table contains user")
		var columns []shim.Column
		col1 := shim.Column{Value: &shim.Column_String_{String_: user}}
		columns = append(columns, col1)

		row, err := stub.GetRow("Shares", columns)
		if err != nil {
			return nil, errors.New("failed in function getRow")
		}

		if len(row.Columns) == 0 {
			fmt.Println("columns 0")
			fmt.Println("started to add a row")

			value, err := strconv.Atoi(amount)
			if err != nil {
				return nil, errors.New("errors in the amount")
			}
			currentSummary += value

			row := shim.Row{
				Columns: []*shim.Column{
					&shim.Column{Value: &shim.Column_String_{String_: user}},
					&shim.Column{Value: &shim.Column_Int64{Int64: int64(value)}}}}

			ok, err := stub.InsertRow("Shares", row)
			if !ok && err == nil {
				return nil, errors.New("shares was already assigned")
			}
		} else {
			fmt.Println("columns not 0")
			fmt.Println("todo we need to update")
		}

		return nil, nil //end of pay
	}

	return nil, nil
}

//Query funciton
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Query()")

	switch function {
	case "getState":
		fmt.Println("started in function getState()")
		if len(args) != 1 {
			return nil, errors.New("incorrect args")
		}

		key := args[0]
		result, err := stub.GetState(key)

		if err != nil {
			return nil, errors.New("Failed in function getState")
		}
		return result, err //end of getState
	case "getProjectState":
		if len(args) != 0 {
			return nil, errors.New("incorrect args")
		}
		fmt.Println("started in function getProjectState")
		result := projectName + "/"
		result += strconv.Itoa(projectRate) + "/"
		result += strconv.Itoa(projectPeriod) + "/"
		result += strconv.Itoa(projectGoal) + "/"
		result += strconv.Itoa(projectTimes) + "/"
		result += projectBenfiary + "/"
		result += strconv.Itoa(currentSummary) + "/"
		result += projectState

		return []byte(result), nil //end of function getProjectState

	case "getRow":
		if len(args) != 1 {
			return nil, errors.New("incorrect args")
		}
		fmt.Println("started logging in function getRow()")

		user := args[0]
		var columns []shim.Column
		col1 := shim.Column{Value: &shim.Column_String_{String_: user}}
		columns = append(columns, col1)

		row, err := stub.GetRow("Shares", columns)
		if err != nil {
			return nil, errors.New("failed in function getRow")
		}

		val0 := row.Columns[0].GetString_()
		val1 := row.Columns[1].GetInt64()
		result := "****" + val0 + "****" + strconv.Itoa(val1)
		return []byte(result), err //end of function getRow()
	}
	return nil, nil
}
<commit_msg>demo06.go<commit_after>package main

import (
	"errors"
	"fmt"
	"strconv"

	"github.com/hyperledger/fabric/core/chaincode/shim"
)

// SimpleChaincode basic struct
type SimpleChaincode struct {
}

func main() {
	fmt.Println("started logging in main()")
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("failed in function main(), error is %v", err)
	}
}

var projectName string
var projectRate int
var projectPeriod, projectGoal, projectTimes int
var projectBenfiary string
var projectState string
var currentPrice float64
var currentSummary int

//Init function
//Step1: 获得调用init()的caller, 并且保存在"admin"中
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Init()")

	//get caller's certificate, and saved to "admin" state
	fmt.Println("started get caller's metatdat")
	adminCert, err := stub.GetCallerCertificate()
	if err != nil {
		return nil, errors.New("failed getting metadata")
	}
	if len(adminCert) == 0 {
		return nil, errors.New("Invalid admin certificate. Empty.")
	}
	fmt.Printf("the administrator is [%v]", adminCert)
	stub.PutState("admin", adminCert)

	//started to initialize project
	fmt.Println("started to initialize project")
	if len(args) != 5 {
		return nil, errors.New("failed in args")
	}
	projectName = args[0]                    //项目名称
	projectRate, _ = strconv.Atoi(args[1])   //项目年化利率
	projectPeriod, _ = strconv.Atoi(args[2]) //项目天数
	projectGoal, _ = strconv.Atoi(args[3])   //项目目标募集金额
	projectTimes = 1                         //项目期数
	projectBenfiary = args[4]                //项目受益人
	projectState = "draft"                   //项目当前状态
	currentPrice = 1.0

	//started to initialize the table: Shares
	fmt.Println("started to create table: Shares")
	tableErr := stub.CreateTable("Shares", []*shim.ColumnDefinition{
		&shim.ColumnDefinition{Name: "User", Type: shim.ColumnDefinition_STRING, Key: true},
		&shim.ColumnDefinition{Name: "Amount", Type: shim.ColumnDefinition_INT64, Key: false},
	})
	if tableErr != nil {
		return nil, errors.New("Failed creating AssetsOnwership table.")
	}

	return nil, nil
}

// Invoke function
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Invoke()")

	switch function {
	case "goPublic":
		if len(args) != 0 {
			return nil, errors.New("failed in args")
		}
		fmt.Println("started logging in goPublic()")
		projectState = "public"
		return nil, nil //end of goPublic
	case "pay":
		if len(args) != 2 {
			return nil, errors.New("failed in args")
		}
		fmt.Println("started logging in pay()")
		user := args[0]
		amount := args[1]

		fmt.Println("step1: chechk whether table contains user")
		var columns []shim.Column
		col1 := shim.Column{Value: &shim.Column_String_{String_: user}}
		columns = append(columns, col1)

		row, err := stub.GetRow("Shares", columns)
		if err != nil {
			return nil, errors.New("failed in function getRow")
		}

		if len(row.Columns) == 0 {
			fmt.Println("columns 0")
			fmt.Println("started to add a row")

			value, err := strconv.Atoi(amount)
			if err != nil {
				return nil, errors.New("errors in the amount")
			}
			currentSummary += value

			row := shim.Row{
				Columns: []*shim.Column{
					&shim.Column{Value: &shim.Column_String_{String_: user}},
					&shim.Column{Value: &shim.Column_Int64{Int64: int64(value)}}}}

			ok, err := stub.InsertRow("Shares", row)
			if !ok && err == nil {
				return nil, errors.New("shares was already assigned")
			}
		} else {
			fmt.Println("columns not 0")
			fmt.Println("todo we need to update")
		}

		return nil, nil //end of pay
	}

	return nil, nil
}

//Query funciton
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Query()")

	switch function {
	case "getState":
		fmt.Println("started in function getState()")
		if len(args) != 1 {
			return nil, errors.New("incorrect args")
		}

		key := args[0]
		result, err := stub.GetState(key)

		if err != nil {
			return nil, errors.New("Failed in function getState")
		}
		return result, err //end of getState
	case "getProjectState":
		if len(args) != 0 {
			return nil, errors.New("incorrect args")
		}
		fmt.Println("started in function getProjectState")
		result := projectName + "/"
		result += strconv.Itoa(projectRate) + "/"
		result += strconv.Itoa(projectPeriod) + "/"
		result += strconv.Itoa(projectGoal) + "/"
		result += strconv.Itoa(projectTimes) + "/"
		result += projectBenfiary + "/"
		result += strconv.Itoa(currentSummary) + "/"
		result += projectState

		return []byte(result), nil //end of function getProjectState

	case "getRow":
		if len(args) != 1 {
			return nil, errors.New("incorrect args")
		}
		fmt.Println("started logging in function getRow()")

		user := args[0]
		var columns []shim.Column
		col1 := shim.Column{Value: &shim.Column_String_{String_: user}}
		columns = append(columns, col1)

		row, err := stub.GetRow("Shares", columns)
		if err != nil {
			return nil, errors.New("failed in function getRow")
		}

		val0 := row.Columns[0].GetString_()
		val1 := int(row.Columns[1].GetInt64())
		result := "****" + val0 + "****" + strconv.Itoa(val1)
		return []byte(result), err //end of function getRow()
	}
	return nil, nil
}
<|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"strconv"

	"github.com/hyperledger/fabric/core/chaincode/shim"
)

type SimpleChaincode struct {
}

var projectName string
var projectRate int
var projectPeriod int
var projectGoal int
var projectTimes int
var projectBenifary string
var projectState string
var currentPrice float64
var projectSummary int
var userList []string

// var shareList map[string]int
// var availableList map[string]int

func main() {
	fmt.Println("started logging in main()")
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Println("failed in function main()")
	}
}

//Init comment
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Init()")

	//started to initialize the projectState
	//step1: check whether args == 5
	if len(args) != 5 {
		return nil, errors.New("failed in args")
	}

	//step 2, intialize the project properties
	projectName = args[0]
	stub.PutState("projectName", []byte(projectName))

	projectRate, _ = strconv.Atoi(args[1])
	if projectRate <= 0 {
		return nil, errors.New("errors in args[1], it cannot be negative")
	}
	stub.PutState("projectRate", []byte(args[1]))

	projectPeriod, _ = strconv.Atoi(args[2])
	if projectPeriod <= 0 {
		return nil, errors.New("errors in args[2], it cannot be negative")
	}
	stub.PutState("projectPeriod", []byte(args[2]))

	projectGoal, _ = strconv.Atoi(args[3])
	if projectGoal <= 0 {
		return nil, errors.New("errors in args[3], it cannot be negative")
	}
	stub.PutState("projectGoal", []byte(args[3]))

	projectTimes = 1
	stub.PutState("projectTimes", []byte(strconv.Itoa(projectTimes)))

	projectBenifary = args[4]
	stub.PutState("projectBenifary", []byte(args[4]))

	projectState = "draft"
	stub.PutState("projectState", []byte(projectState))

	currentPrice = 1.0
	projectSummary = 0

	return nil, nil
} //end of Init()

// Invoke comment
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Invoke()")
	switch function {
	case "goPublic":
		fmt.Println("started logging in goPublic")
		if len(args) != 0 {
			return nil, errors.New("failed in args")
		}
		projectState = "public"
		return nil, nil //end of goPublic
	case "pay":
		fmt.Println("started logging in pay()")

		if len(args) != 2 {
			return nil, errors.New("failed in args")
		}
		user := args[0]
		amount := args[1]
		fmt.Printf("user is %v and amount is %v\n", user, amount)
		amountInt, _ := strconv.Atoi(amount)
		if amountInt <= 0 {
			return nil, errors.New("amount is negative")
		}

		userList = append(userList, user)

		// value := shareList[user]
		// value += amountInt
		// shareList[user] = value

		projectSummary += amountInt
		return nil, nil
	case "checkGoalReached":
		fmt.Println("started logging in checkGoalReached()")
		// TODO: write code for checkGoalReached
		return nil, nil
	case "checkDaoqi":
		fmt.Println("started logging in checkDaoqi()")
		// TODO: write code for checkDaoqi
		return nil, nil
	case "calculatePrice":
		fmt.Println("started logging in calculatePrice")
		return nil, nil
	case "calculateResult":
		fmt.Println("started logging in calculateResult")
		return nil, nil
	}
	return nil, nil
}

// Query comment
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Query()")
	switch function {
	case "getProjectName":
		result, err := stub.GetState("projectName")
		if err != nil {
			return nil, errors.New("error in getProjectName")
		}
		return result, nil
	case "getProjectGoal":
		result, err := stub.GetState("projectGoal")
		if err != nil {
			return nil, errors.New("error in getProjectGoal")
		}
		return result, nil
	case "getProjectSummary":
		result := strconv.Itoa(projectSummary)
		return []byte(result), nil
	case "getUserList":
		fmt.Println("started logging in getUserList")
		var result string
		for i, value := range userList {
			result += fmt.Sprintf("userList[%v] is %v ****", strconv.Itoa(i), value)
		}
		return []byte(result), nil
	case "getShareList":
		fmt.Println("started logging in getShareList")
		return nil, nil
	case "getAvailableList":
		fmt.Println("started logging in getAvailableList")
		return nil, nil
	}
	return nil, nil
}
<commit_msg>demo7.go<commit_after>package main

import (
	"errors"
	"fmt"
	"strconv"

	"github.com/hyperledger/fabric/core/chaincode/shim"
)

type SimpleChaincode struct {
}

var projectName string
var projectRate int
var projectPeriod int
var projectGoal int
var projectTimes int
var projectBenifary string
var projectState string
var currentPrice float64
var projectSummary int
var userList []string

// var shareList map[string]int
// var availableList map[string]int

func main() {
	fmt.Println("started logging in main()")
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Println("failed in function main()")
	}
}

//Init comment
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Init()")

	//started to initialize the projectState
	//step1: check whether args == 5
	if len(args) != 5 {
		return nil, errors.New("failed in args")
	}

	//step 2, intialize the project properties
	projectName = args[0]
	stub.PutState("projectName", []byte(projectName))

	projectRate, _ = strconv.Atoi(args[1])
	if projectRate <= 0 {
		return nil, errors.New("errors in args[1], it cannot be negative")
	}
	stub.PutState("projectRate", []byte(args[1]))

	projectPeriod, _ = strconv.Atoi(args[2])
	if projectPeriod <= 0 {
		return nil, errors.New("errors in args[2], it cannot be negative")
	}
	stub.PutState("projectPeriod", []byte(args[2]))

	projectGoal, _ = strconv.Atoi(args[3])
	if projectGoal <= 0 {
		return nil, errors.New("errors in args[3], it cannot be negative")
	}
	stub.PutState("projectGoal", []byte(args[3]))

	projectTimes = 1
	stub.PutState("projectTimes", []byte(strconv.Itoa(projectTimes)))

	projectBenifary = args[4]
	stub.PutState("projectBenifary", []byte(args[4]))

	projectState = "draft"
	stub.PutState("projectState", []byte(projectState))

	currentPrice = 1.0
	projectSummary = 0

	return nil, nil
} //end of Init()

// Invoke comment
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Invoke()")
	switch function {
	case "goPublic":
		fmt.Println("started logging in goPublic")
		if len(args) != 0 {
			return nil, errors.New("failed in args")
		}
		projectState = "public"
		return nil, nil //end of goPublic
	case "pay":
		fmt.Println("started logging in pay()")

		if len(args) != 2 {
			return nil, errors.New("failed in args")
		}
		user := args[0]
		amount := args[1]
		fmt.Printf("user is %v and amount is %v\n", user, amount)
		amountInt, _ := strconv.Atoi(amount)
		if amountInt <= 0 {
			return nil, errors.New("amount is negative")
		}

		// userList = append(userList, user)

		// value := shareList[user]
		// value += amountInt
		// shareList[user] = value

		projectSummary += amountInt
		return nil, nil
	case "checkGoalReached":
		fmt.Println("started logging in checkGoalReached()")
		// TODO: write code for checkGoalReached
		return nil, nil
	case "checkDaoqi":
		fmt.Println("started logging in checkDaoqi()")
		// TODO: write code for checkDaoqi
		return nil, nil
	case "calculatePrice":
		fmt.Println("started logging in calculatePrice")
		return nil, nil
	case "calculateResult":
		fmt.Println("started logging in calculateResult")
		return nil, nil
	}
	return nil, nil
}

// Query comment
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
	fmt.Println("started logging in Query()")
	switch function {
	case "getProjectName":
		result, err := stub.GetState("projectName")
		if err != nil {
			return nil, errors.New("error in getProjectName")
		}
		return result, nil
	case "getProjectGoal":
		result, err := stub.GetState("projectGoal")
		if err != nil {
			return nil, errors.New("error in getProjectGoal")
		}
		return result, nil
	case "getProjectSummary":
		result := strconv.Itoa(projectSummary)
		return []byte(result), nil
	case "getUserList":
		fmt.Println("started logging in getUserList")
		var result string
		for i, value := range userList {
			result += fmt.Sprintf("userList[%v] is %v ****", strconv.Itoa(i), value)
		}
		return []byte(result), nil
	case "getShareList":
		fmt.Println("started logging in getShareList")
		return nil, nil
	case "getAvailableList":
		fmt.Println("started logging in getAvailableList")
		return nil, nil
	}
	return nil, nil
}
<|endoftext|>


<commit_before>package godirwalk

import (
	"fmt"
	"sort"
	"strings"
	"testing"
)

func ensureError(tb testing.TB, err error, contains ...string) {
	tb.Helper()
	if len(contains) == 0 || (len(contains) == 1 && contains[0] == "") {
		if err != nil {
			tb.Errorf("GOT: %v; WANT: %v", err, contains)
		}
	} else if err == nil {
		tb.Errorf("GOT: %v; WANT: %v", err, contains)
	} else {
		for _, stub := range contains {
			if stub != "" && !strings.Contains(err.Error(), stub) {
				tb.Errorf("GOT: %v; WANT: %q", err, stub)
			}
		}
	}
}

func ensureStringSlicesMatch(tb testing.TB, actual, expected []string) {
	tb.Helper()

	results := make(map[string]int)

	for _, s := range actual {
		results[s] = -1
	}
	for _, s := range expected {
		results[s]++
	}

	keys := make([]string, 0, len(results))
	for k := range results {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	for _, s := range keys {
		v, ok := results[s]
		if !ok {
			panic(fmt.Errorf("cannot find key: %s", s)) // panic because this function is broken
		}
		switch v {
		case -1:
			tb.Errorf("GOT: %q (extra)", s)
		case 0:
			// both slices have this key
		case 1:
			tb.Errorf("WANT: %q (missing)", s)
		default:
			panic(fmt.Errorf("key has invalid value: %s: %d", s, v)) // panic because this function is broken
		}
	}
}
<commit_msg>EnsureError fatal when unexpected error<commit_after>package godirwalk

import (
	"fmt"
	"sort"
	"strings"
	"testing"
)

func ensureError(tb testing.TB, err error, contains ...string) {
	tb.Helper()
	if len(contains) == 0 || (len(contains) == 1 && contains[0] == "") {
		if err != nil {
			tb.Fatalf("GOT: %v; WANT: %v", err, contains)
		}
	} else if err == nil {
		tb.Errorf("GOT: %v; WANT: %v", err, contains)
	} else {
		for _, stub := range contains {
			if stub != "" && !strings.Contains(err.Error(), stub) {
				tb.Errorf("GOT: %v; WANT: %q", err, stub)
			}
		}
	}
}

func ensureStringSlicesMatch(tb testing.TB, actual, expected []string) {
	tb.Helper()

	results := make(map[string]int)

	for _, s := range actual {
		results[s] = -1
	}
	for _, s := range expected {
		results[s]++
	}

	keys := make([]string, 0, len(results))
	for k := range results {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	for _, s := range keys {
		v, ok := results[s]
		if !ok {
			panic(fmt.Errorf("cannot find key: %s", s)) // panic because this function is broken
		}
		switch v {
		case -1:
			tb.Errorf("GOT: %q (extra)", s)
		case 0:
			// both slices have this key
		case 1:
			tb.Errorf("WANT: %q (missing)", s)
		default:
			panic(fmt.Errorf("key has invalid value: %s: %d", s, v)) // panic because this function is broken
		}
	}
}
<|endoftext|>