<commit_before>package buildkite

import "fmt"
import "strings"

// You can overriden buildVersion at compile time by using:
//
//  go run -ldflags "-X github.com/buildkite/agent/buildkite.buildVersion abc" *.go --version
//
// On CI, the binaries are always build with the buildVersion variable set.

var baseVersion string = "1.0-beta.19"
var buildVersion string = ""

func Version() string {
	// Only output the build version if a pre-release
	if strings.Contains(baseVersion, "beta") || strings.Contains(baseVersion, "alpha") {
		// Use a default buildVersion if one doesn't exist
		actualBuildVersion := buildVersion
		if actualBuildVersion == "" {
			actualBuildVersion = "x"
		}

		return fmt.Sprintf("%s.%s", baseVersion, actualBuildVersion)
	} else {
		return baseVersion
	}
}
<commit_msg>Bumping to 1.0-beta.20<commit_after>package buildkite

import "fmt"
import "strings"

// You can overriden buildVersion at compile time by using:
//
//  go run -ldflags "-X github.com/buildkite/agent/buildkite.buildVersion abc" *.go --version
//
// On CI, the binaries are always build with the buildVersion variable set.

var baseVersion string = "1.0-beta.20"
var buildVersion string = ""

func Version() string {
	// Only output the build version if a pre-release
	if strings.Contains(baseVersion, "beta") || strings.Contains(baseVersion, "alpha") {
		// Use a default buildVersion if one doesn't exist
		actualBuildVersion := buildVersion
		if actualBuildVersion == "" {
			actualBuildVersion = "x"
		}

		return fmt.Sprintf("%s.%s", baseVersion, actualBuildVersion)
	} else {
		return baseVersion
	}
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"sort"
	"strconv"
)

func check(e error) {
	if e != nil {
		panic(e)
	}
}

func pairArraySum(items []int) int {
	sort.Ints(items)

	sum, prev := 0, 0

	pivot := sort.SearchInts(items, 2)

	for _, cur := range items[:pivot] {
		switch {
		case cur < 0:
			if prev != 0 {
				sum += prev * cur
				prev = 0
			} else {
				prev = cur
			}
		case cur == 0:
			prev = 0
		case cur == 1:
			sum += 1
		}
	}
	sum += prev
	prev = 0

	items = items[pivot:]

	for i := len(items) - 1; i >= 0; i-- {
		if prev != 0 {
			sum += prev * items[i]
			prev = 0
		} else {
			prev = items[i]
		}
	}
	sum += prev

	return sum
}

func parseFile(fileName string) []int {
	f, err := os.Open(fileName)
	check(err)

	scanner := bufio.NewScanner(f)

	scanner.Split(bufio.ScanWords)

	var items []int

	for scanner.Scan() {
		i, e := strconv.Atoi(scanner.Text())
		check(e)
		items = append(items, i)
	}
	return items
}

func processFile(fileName string) int {
	items := parseFile(fileName)
	return pairArraySum(items)
}

func main() {
	fileName := flag.String("file", "sample.txt", "source file")
	flag.Parse()

	result := processFile(*fileName)
	fmt.Println(result)
}
<commit_msg>Improve sum function logic to avoid an extra search in the array reducing the complexity of the code<commit_after>package main

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"sort"
	"strconv"
)

func check(e error) {
	if e != nil {
		panic(e)
	}
}

func findMaxPairSum(items []int) int {

	sort.Ints(items)

	sum, prev := 0, 0

	var positives []int

	for i, cur := range items {

		if cur < 0 {
			if prev == 0 {
				prev = cur
			} else {
				sum += prev * cur
				prev = 0
			}
		} else if cur == 0 {
			prev = 0
		} else if cur == 1 {
			sum += 1
		} else {
			positives = items[i:]
			break
		}
	}

	sum += prev
	prev = 0

	for i := len(positives) - 1; i >= 0; i-- {
		if prev != 0 {
			sum += prev * positives[i]
			prev = 0
		} else {
			prev = positives[i]
		}
	}
	return sum + prev
}

func parseFile(fileName string) []int {
	f, err := os.Open(fileName)
	check(err)

	scanner := bufio.NewScanner(f)

	scanner.Split(bufio.ScanWords)

	var items []int

	for scanner.Scan() {
		i, e := strconv.Atoi(scanner.Text())
		check(e)
		items = append(items, i)
	}
	return items
}

func processFile(fileName string) int {
	items := parseFile(fileName)
	return findMaxPairSum(items)
}

func main() {
	fileName := flag.String("file", "sample.txt", "source file")
	flag.Parse()

	result := processFile(*fileName)
	fmt.Println(result)
}<|endoftext|>


<commit_before>// Copyright 2017 The Ebiten Authors
//
// 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.

// +build !js

package mp3

import (
	"fmt"
	"io"
)

var g_mpeg1_bitrates = map[mpeg1Layer][15]int{
	mpeg1Layer1: {
		0, 32000, 64000, 96000, 128000, 160000, 192000, 224000,
		256000, 288000, 320000, 352000, 384000, 416000, 448000,
	},
	mpeg1Layer2: {
		0, 32000, 48000, 56000, 64000, 80000, 96000, 112000,
		128000, 160000, 192000, 224000, 256000, 320000, 384000,
	},
	mpeg1Layer3: {
		0, 32000, 40000, 48000, 56000, 64000, 80000, 96000,
		112000, 128000, 160000, 192000, 224000, 256000, 320000,
	},
}

var g_sampling_frequency = [3]int{44100, 48000, 32000}

func (f *frame) readAudioL3() error {
	nch := f.numberOfChannels()
	/* Calculate header audio data size */
	framesize := (144*
		g_mpeg1_bitrates[f.header.layer][f.header.bitrate_index])/
		g_sampling_frequency[f.header.sampling_frequency] +
		int(f.header.padding_bit)
	if framesize > 2000 {
		return fmt.Errorf("mp3: framesize = %d\n", framesize)
	}
	/* Sideinfo is 17 bytes for one channel and 32 bytes for two */
	sideinfo_size := 32
	if nch == 1 {
		sideinfo_size = 17
	}
	/* Main data size is the rest of the frame,including ancillary data */
	main_data_size := framesize - sideinfo_size - 4 /* sync+header */
	/* CRC is 2 bytes */
	if f.header.protection_bit == 0 {
		main_data_size -= 2
	}
	/* Read sideinfo from bitstream into buffer used by getSideBits() */
	if err := getSideinfo(sideinfo_size); err != nil {
		return err
	}
	/* Parse audio data */
	/* Pointer to where we should start reading main data */
	f.sideInfo.main_data_begin = getSideBits(9)
	/* Get private bits. Not used for anything. */
	if f.header.mode == mpeg1ModeSingleChannel {
		f.sideInfo.private_bits = getSideBits(5)
	} else {
		f.sideInfo.private_bits = getSideBits(3)
	}
	/* Get scale factor selection information */
	for ch := 0; ch < nch; ch++ {
		for scfsi_band := 0; scfsi_band < 4; scfsi_band++ {
			f.sideInfo.scfsi[ch][scfsi_band] = getSideBits(1)
		}
	}
	/* Get the rest of the side information */
	for gr := 0; gr < 2; gr++ {
		for ch := 0; ch < nch; ch++ {
			f.sideInfo.part2_3_length[gr][ch] = getSideBits(12)
			f.sideInfo.big_values[gr][ch] = getSideBits(9)
			f.sideInfo.global_gain[gr][ch] = getSideBits(8)
			f.sideInfo.scalefac_compress[gr][ch] = getSideBits(4)
			f.sideInfo.win_switch_flag[gr][ch] = getSideBits(1)
			if f.sideInfo.win_switch_flag[gr][ch] == 1 {
				f.sideInfo.block_type[gr][ch] = getSideBits(2)
				f.sideInfo.mixed_block_flag[gr][ch] = getSideBits(1)
				for region := 0; region < 2; region++ {
					f.sideInfo.table_select[gr][ch][region] = getSideBits(5)
				}
				for window := 0; window < 3; window++ {
					f.sideInfo.subblock_gain[gr][ch][window] = getSideBits(3)
				}
				if (f.sideInfo.block_type[gr][ch] == 2) && (f.sideInfo.mixed_block_flag[gr][ch] == 0) {
					f.sideInfo.region0_count[gr][ch] = 8 /* Implicit */
				} else {
					f.sideInfo.region0_count[gr][ch] = 7 /* Implicit */
				}
				/* The standard is wrong on this!!! */ /* Implicit */
				f.sideInfo.region1_count[gr][ch] = 20 - f.sideInfo.region0_count[gr][ch]
			} else {
				for region := 0; region < 3; region++ {
					f.sideInfo.table_select[gr][ch][region] = getSideBits(5)
				}
				f.sideInfo.region0_count[gr][ch] = getSideBits(4)
				f.sideInfo.region1_count[gr][ch] = getSideBits(3)
				f.sideInfo.block_type[gr][ch] = 0 /* Implicit */
			}
			f.sideInfo.preflag[gr][ch] = getSideBits(1)
			f.sideInfo.scalefac_scale[gr][ch] = getSideBits(1)
			f.sideInfo.count1table_select[gr][ch] = getSideBits(1)
		}
	}
	return nil
}

// A sideInfo is a bit reservoir for side info
type sideInfo struct {
	vec []int
	idx int // Index into the current byte(0-7)
}

var theSideInfo sideInfo

func getSideinfo(size int) error {
	buf := make([]int, size)
	n := 0
	var err error
	for n < size && err == nil {
		nn, err2 := getBytes(buf[n:])
		n += nn
		err = err2
	}
	if n < size {
		if err == io.EOF {
			return fmt.Errorf("mp3: unexpected EOF at getSideinfo")
		}
		return fmt.Errorf("mp3: couldn't read sideinfo %d bytes at pos %d: %v",
			size, getFilepos(), err)
	}
	theSideInfo.vec = buf[:n]
	theSideInfo.idx = 0
	return nil
}

func getSideBits(num int) int {
	// Form a word of the next four bytes
	// TODO: endianness?
	b := make([]int, 4)
	for i := range b {
		if len(theSideInfo.vec) > i {
			b[i] = theSideInfo.vec[i]
		}
	}
	tmp := (uint32(b[0]) << 24) | (uint32(b[1]) << 16) | (uint32(b[2]) << 8) | (uint32(b[3]) << 0)
	// Remove bits already used
	tmp = tmp << uint(theSideInfo.idx)
	// Remove bits after the desired bits
	tmp = tmp >> (32 - uint(num))
	// Update pointers
	theSideInfo.vec = theSideInfo.vec[(theSideInfo.idx+int(num))>>3:]
	theSideInfo.idx = (theSideInfo.idx + int(num)) & 0x07
	return int(tmp)
}
<commit_msg>audio/mp3: Remove global variable 'theSideInfo'<commit_after>// Copyright 2017 The Ebiten Authors
//
// 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.

// +build !js

package mp3

import (
	"fmt"
	"io"
)

var g_mpeg1_bitrates = map[mpeg1Layer][15]int{
	mpeg1Layer1: {
		0, 32000, 64000, 96000, 128000, 160000, 192000, 224000,
		256000, 288000, 320000, 352000, 384000, 416000, 448000,
	},
	mpeg1Layer2: {
		0, 32000, 48000, 56000, 64000, 80000, 96000, 112000,
		128000, 160000, 192000, 224000, 256000, 320000, 384000,
	},
	mpeg1Layer3: {
		0, 32000, 40000, 48000, 56000, 64000, 80000, 96000,
		112000, 128000, 160000, 192000, 224000, 256000, 320000,
	},
}

var g_sampling_frequency = [3]int{44100, 48000, 32000}

func (f *frame) readAudioL3() error {
	nch := f.numberOfChannels()
	/* Calculate header audio data size */
	framesize := (144*
		g_mpeg1_bitrates[f.header.layer][f.header.bitrate_index])/
		g_sampling_frequency[f.header.sampling_frequency] +
		int(f.header.padding_bit)
	if framesize > 2000 {
		return fmt.Errorf("mp3: framesize = %d\n", framesize)
	}
	/* Sideinfo is 17 bytes for one channel and 32 bytes for two */
	sideinfo_size := 32
	if nch == 1 {
		sideinfo_size = 17
	}
	/* Main data size is the rest of the frame,including ancillary data */
	main_data_size := framesize - sideinfo_size - 4 /* sync+header */
	/* CRC is 2 bytes */
	if f.header.protection_bit == 0 {
		main_data_size -= 2
	}
	/* Read sideinfo from bitstream into buffer used by getSideBits() */
	s, err := getSideinfo(sideinfo_size)
	if err != nil {
		return err
	}
	/* Parse audio data */
	/* Pointer to where we should start reading main data */
	f.sideInfo.main_data_begin = s.getSideBits(9)
	/* Get private bits. Not used for anything. */
	if f.header.mode == mpeg1ModeSingleChannel {
		f.sideInfo.private_bits = s.getSideBits(5)
	} else {
		f.sideInfo.private_bits = s.getSideBits(3)
	}
	/* Get scale factor selection information */
	for ch := 0; ch < nch; ch++ {
		for scfsi_band := 0; scfsi_band < 4; scfsi_band++ {
			f.sideInfo.scfsi[ch][scfsi_band] = s.getSideBits(1)
		}
	}
	/* Get the rest of the side information */
	for gr := 0; gr < 2; gr++ {
		for ch := 0; ch < nch; ch++ {
			f.sideInfo.part2_3_length[gr][ch] = s.getSideBits(12)
			f.sideInfo.big_values[gr][ch] = s.getSideBits(9)
			f.sideInfo.global_gain[gr][ch] = s.getSideBits(8)
			f.sideInfo.scalefac_compress[gr][ch] = s.getSideBits(4)
			f.sideInfo.win_switch_flag[gr][ch] = s.getSideBits(1)
			if f.sideInfo.win_switch_flag[gr][ch] == 1 {
				f.sideInfo.block_type[gr][ch] = s.getSideBits(2)
				f.sideInfo.mixed_block_flag[gr][ch] = s.getSideBits(1)
				for region := 0; region < 2; region++ {
					f.sideInfo.table_select[gr][ch][region] = s.getSideBits(5)
				}
				for window := 0; window < 3; window++ {
					f.sideInfo.subblock_gain[gr][ch][window] = s.getSideBits(3)
				}
				if (f.sideInfo.block_type[gr][ch] == 2) && (f.sideInfo.mixed_block_flag[gr][ch] == 0) {
					f.sideInfo.region0_count[gr][ch] = 8 /* Implicit */
				} else {
					f.sideInfo.region0_count[gr][ch] = 7 /* Implicit */
				}
				/* The standard is wrong on this!!! */ /* Implicit */
				f.sideInfo.region1_count[gr][ch] = 20 - f.sideInfo.region0_count[gr][ch]
			} else {
				for region := 0; region < 3; region++ {
					f.sideInfo.table_select[gr][ch][region] = s.getSideBits(5)
				}
				f.sideInfo.region0_count[gr][ch] = s.getSideBits(4)
				f.sideInfo.region1_count[gr][ch] = s.getSideBits(3)
				f.sideInfo.block_type[gr][ch] = 0 /* Implicit */
			}
			f.sideInfo.preflag[gr][ch] = s.getSideBits(1)
			f.sideInfo.scalefac_scale[gr][ch] = s.getSideBits(1)
			f.sideInfo.count1table_select[gr][ch] = s.getSideBits(1)
		}
	}
	return nil
}

// A sideInfo is a bit reservoir for side info
type sideInfo struct {
	vec []int
	idx int // Index into the current byte(0-7)
}

func getSideinfo(size int) (*sideInfo, error) {
	buf := make([]int, size)
	n := 0
	var err error
	for n < size && err == nil {
		nn, err2 := getBytes(buf[n:])
		n += nn
		err = err2
	}
	if n < size {
		if err == io.EOF {
			return nil, fmt.Errorf("mp3: unexpected EOF at getSideinfo")
		}
		return nil, fmt.Errorf("mp3: couldn't read sideinfo %d bytes at pos %d: %v",
			size, getFilepos(), err)
	}
	s := &sideInfo{
		vec: buf[:n],
	}
	return s, nil
}

func (s *sideInfo) getSideBits(num int) int {
	// Form a word of the next four bytes
	// TODO: endianness?
	b := make([]int, 4)
	for i := range b {
		if len(s.vec) > i {
			b[i] = s.vec[i]
		}
	}
	tmp := (uint32(b[0]) << 24) | (uint32(b[1]) << 16) | (uint32(b[2]) << 8) | (uint32(b[3]) << 0)
	// Remove bits already used
	tmp = tmp << uint(s.idx)
	// Remove bits after the desired bits
	tmp = tmp >> (32 - uint(num))
	// Update pointers
	s.vec = s.vec[(s.idx+int(num))>>3:]
	s.idx = (s.idx + int(num)) & 0x07
	return int(tmp)
}
<|endoftext|>


<commit_before>package main

import (
	"html/template"
	"log"
	"net/http"
	"sort"

	"github.com/eknkc/amber"
)

//template map
var templateMap map[string]*template.Template

//initialization of the template map
func init() {
	templateMap, _ = amber.CompileDir("src/views",
		amber.DirOptions{Ext: ".amber", Recursive: true},
		amber.Options{PrettyPrint: false, LineNumbers: false})
}

//complete web server function
func webServer() {
	//Sets path handler funcions
	http.HandleFunc("/", animeHandler)
	http.HandleFunc("/static/", staticHandler)

	log.Println("Starting http server...")

	http.ListenAndServe(":80", nil)
}

// /anime path handler
func animeHandler(w http.ResponseWriter, r *http.Request) {
	data := getAnimeList()
	sort.Sort(data)
	templateMap["aList"].Execute(w, data)
}

// /static/* file server
func staticHandler(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, "src/"+r.URL.Path[1:])
}
<commit_msg>filter outdated data out of webpage<commit_after>package main

import (
	"html/template"
	"log"
	"net/http"
	"sort"

	"github.com/eknkc/amber"
)

//template map
var templateMap map[string]*template.Template

//initialization of the template map
func init() {
	templateMap, _ = amber.CompileDir("src/views",
		amber.DirOptions{Ext: ".amber", Recursive: true},
		amber.Options{PrettyPrint: false, LineNumbers: false})
}

//complete web server function
func webServer() {
	//Sets path handler funcions
	http.HandleFunc("/", animeHandler)
	http.HandleFunc("/static/", staticHandler)

	log.Println("Starting http server...")

	http.ListenAndServe(":80", nil)
}

// / path handler
func animeHandler(w http.ResponseWriter, r *http.Request) {
	data := getAnimeList()
	var shownData animeList

	for _, a := range data {
		if a.Show {
			shownData = append(shownData, a)
		}
	}

	sort.Sort(shownData)
	templateMap["aList"].Execute(w, shownData)
}

// /static/* file server
func staticHandler(w http.ResponseWriter, r *http.Request) {
	http.ServeFile(w, r, "src/"+r.URL.Path[1:])
}
<|endoftext|>


<commit_before>package chain

import (
	"fmt"
	"github.com/pierrre/imageserver"
)

type ChainCache []imageserver.Cache

func (cache ChainCache) Get(key string, parameters imageserver.Parameters) (*imageserver.Image, error) {
	for i, c := range cache {
		image, err := c.Get(key, parameters)
		if err == nil {
			if i > 0 {
				cache.setCaches(key, image, parameters, i)
			}
			return image, nil
		}
	}
	return nil, fmt.Errorf("Image not found in chained cache")
}

func (cache ChainCache) setCaches(key string, image *imageserver.Image, parameters imageserver.Parameters, indexLimit int) {
	for i := 0; i < indexLimit; i++ {
		go func(i int) {
			cache[i].Set(key, image, parameters)
		}(i)
	}
}

func (cache ChainCache) Set(key string, image *imageserver.Image, parameters imageserver.Parameters) (err error) {
	for _, c := range cache {
		go func(c imageserver.Cache) {
			c.Set(key, image, parameters)
		}(c)
	}
	return
}
<commit_msg>Clean ChainCache<commit_after>package chain

import (
	"fmt"
	"github.com/pierrre/imageserver"
)

type ChainCache []imageserver.Cache

func (cache ChainCache) Get(key string, parameters imageserver.Parameters) (*imageserver.Image, error) {
	for i, c := range cache {
		if image, err := c.Get(key, parameters); err == nil {
			if i > 0 {
				cache.setCaches(key, image, parameters, i)
			}
			return image, nil
		}
	}
	return nil, fmt.Errorf("Image not found in chained cache")
}

func (cache ChainCache) setCaches(key string, image *imageserver.Image, parameters imageserver.Parameters, indexLimit int) {
	for i := 0; i < indexLimit; i++ {
		go func(i int) {
			cache[i].Set(key, image, parameters)
		}(i)
	}
}

func (cache ChainCache) Set(key string, image *imageserver.Image, parameters imageserver.Parameters) error {
	for _, c := range cache {
		go func(c imageserver.Cache) {
			c.Set(key, image, parameters)
		}(c)
	}
	return nil
}
<|endoftext|>


<commit_before>package redis

import (
	"bytes"
	"encoding/gob"
	"reflect"
	"time"

	"cloud.google.com/go/datastore"
	"github.com/acoshift/ds"
	"github.com/garyburd/redigo/redis"
)

// Cache implement Cache interface
type Cache struct {
	Pool      *redis.Pool
	Prefix    string
	TTL       time.Duration
	ExtendTTL bool
	Skip      func(*datastore.Key) bool
}

func encode(v interface{}) ([]byte, error) {
	w := &bytes.Buffer{}
	err := gob.NewEncoder(w).Encode(v)
	if err != nil {
		return nil, err
	}
	return w.Bytes(), nil
}

func decode(b []byte, v interface{}) error {
	return gob.NewDecoder(bytes.NewReader(b)).Decode(v)
}

// Get gets data
func (cache *Cache) Get(key *datastore.Key, dst interface{}) error {
	if cache.Skip != nil && cache.Skip(key) {
		return ds.ErrCacheNotFound
	}

	db := cache.Pool.Get()
	defer db.Close()
	k := cache.Prefix + key.String()
	b, err := redis.Bytes(db.Do("GET", k))
	if err != nil {
		return err
	}
	if len(b) == 0 {
		return ds.ErrCacheNotFound
	}
	if cache.ExtendTTL {
		db.Do("EXPIRE", k, int(cache.TTL/time.Second))
	}
	return decode(b, dst)
}

// GetMulti gets multi data
func (cache *Cache) GetMulti(keys []*datastore.Key, dst interface{}) error {
	db := cache.Pool.Get()
	defer db.Close()
	for _, key := range keys {
		db.Send("GET", cache.Prefix+key.String())
	}
	err := db.Flush()
	if err != nil {
		return err
	}
	for i := range keys {
		b, err := redis.Bytes(db.Receive())
		if err != nil {
			return err
		}
		if len(b) > 0 {
			decode(b, reflect.Indirect(reflect.ValueOf(dst)).Index(i).Interface())
		}
	}
	if cache.ExtendTTL {
		ttl := int(cache.TTL / time.Second)
		for _, key := range keys {
			db.Send("EXPIRE", cache.Prefix+key.String(), ttl)
		}
		db.Flush()
	}
	return nil
}

// Set sets data
func (cache *Cache) Set(key *datastore.Key, src interface{}) error {
	if key == nil || src == nil {
		return nil
	}
	if cache.Skip != nil && cache.Skip(key) {
		return nil
	}

	db := cache.Pool.Get()
	defer db.Close()
	b, err := encode(src)
	if err != nil {
		return err
	}
	if cache.TTL > 0 {
		_, err = db.Do("SETEX", cache.Prefix+key.String(), int(cache.TTL/time.Second), b)
		return err
	}
	_, err = db.Do("SET", cache.Prefix+key.String(), b)
	return err
}

// SetMulti sets data
func (cache *Cache) SetMulti(keys []*datastore.Key, src interface{}) error {
	db := cache.Pool.Get()
	defer db.Close()
	ttl := int(cache.TTL / time.Second)
	db.Send("MULTI")
	for i, key := range keys {
		if key == nil {
			continue
		}
		if cache.Skip != nil && cache.Skip(key) {
			continue
		}
		s := reflect.Indirect(reflect.ValueOf(src)).Index(i)
		if s.IsNil() {
			continue
		}
		b, err := encode(s.Interface())
		if err != nil {
			return err
		}
		if cache.TTL > 0 {
			db.Send("SETEX", cache.Prefix+key.String(), ttl, b)
		} else {
			db.Send("SET", cache.Prefix+key.String(), b)
		}
	}
	_, err := db.Do("EXEC")
	return err
}

// Del dels data
func (cache *Cache) Del(key *datastore.Key) error {
	if key == nil {
		return nil
	}
	if cache.Skip != nil && cache.Skip(key) {
		return nil
	}

	db := cache.Pool.Get()
	defer db.Close()
	_, err := db.Do("DEL", cache.Prefix+key.String())
	return err
}

// DelMulti dels multi data
func (cache *Cache) DelMulti(keys []*datastore.Key) error {
	db := cache.Pool.Get()
	defer db.Close()
	db.Send("MULTI")
	for _, key := range keys {
		if key == nil {
			continue
		}
		if cache.Skip != nil && cache.Skip(key) {
			continue
		}
		db.Send("DEL", cache.Prefix+key.String())
	}
	_, err := db.Do("EXEC")
	return err
}
<commit_msg>ignore nil error<commit_after>package redis

import (
	"bytes"
	"encoding/gob"
	"reflect"
	"time"

	"cloud.google.com/go/datastore"
	"github.com/acoshift/ds"
	"github.com/garyburd/redigo/redis"
)

// Cache implement Cache interface
type Cache struct {
	Pool      *redis.Pool
	Prefix    string
	TTL       time.Duration
	ExtendTTL bool
	Skip      func(*datastore.Key) bool
}

func encode(v interface{}) ([]byte, error) {
	w := &bytes.Buffer{}
	err := gob.NewEncoder(w).Encode(v)
	if err != nil {
		return nil, err
	}
	return w.Bytes(), nil
}

func decode(b []byte, v interface{}) error {
	return gob.NewDecoder(bytes.NewReader(b)).Decode(v)
}

// Get gets data
func (cache *Cache) Get(key *datastore.Key, dst interface{}) error {
	if cache.Skip != nil && cache.Skip(key) {
		return ds.ErrCacheNotFound
	}

	db := cache.Pool.Get()
	defer db.Close()
	k := cache.Prefix + key.String()
	b, err := redis.Bytes(db.Do("GET", k))
	if err != nil {
		return err
	}
	if len(b) == 0 {
		return ds.ErrCacheNotFound
	}
	if cache.ExtendTTL {
		db.Do("EXPIRE", k, int(cache.TTL/time.Second))
	}
	return decode(b, dst)
}

// GetMulti gets multi data
func (cache *Cache) GetMulti(keys []*datastore.Key, dst interface{}) error {
	db := cache.Pool.Get()
	defer db.Close()
	for _, key := range keys {
		db.Send("GET", cache.Prefix+key.String())
	}
	err := db.Flush()
	if err != nil {
		return err
	}
	for i := range keys {
		b, err := redis.Bytes(db.Receive())
		if err == redis.ErrNil {
			continue
		}
		if err != nil {
			return err
		}
		if len(b) > 0 {
			decode(b, reflect.Indirect(reflect.ValueOf(dst)).Index(i).Interface())
		}
	}
	if cache.ExtendTTL {
		ttl := int(cache.TTL / time.Second)
		for _, key := range keys {
			db.Send("EXPIRE", cache.Prefix+key.String(), ttl)
		}
		db.Flush()
	}
	return nil
}

// Set sets data
func (cache *Cache) Set(key *datastore.Key, src interface{}) error {
	if key == nil || src == nil {
		return nil
	}
	if cache.Skip != nil && cache.Skip(key) {
		return nil
	}

	db := cache.Pool.Get()
	defer db.Close()
	b, err := encode(src)
	if err != nil {
		return err
	}
	if cache.TTL > 0 {
		_, err = db.Do("SETEX", cache.Prefix+key.String(), int(cache.TTL/time.Second), b)
		return err
	}
	_, err = db.Do("SET", cache.Prefix+key.String(), b)
	return err
}

// SetMulti sets data
func (cache *Cache) SetMulti(keys []*datastore.Key, src interface{}) error {
	db := cache.Pool.Get()
	defer db.Close()
	ttl := int(cache.TTL / time.Second)
	db.Send("MULTI")
	for i, key := range keys {
		if key == nil {
			continue
		}
		if cache.Skip != nil && cache.Skip(key) {
			continue
		}
		s := reflect.Indirect(reflect.ValueOf(src)).Index(i)
		if s.IsNil() {
			continue
		}
		b, err := encode(s.Interface())
		if err != nil {
			return err
		}
		if cache.TTL > 0 {
			db.Send("SETEX", cache.Prefix+key.String(), ttl, b)
		} else {
			db.Send("SET", cache.Prefix+key.String(), b)
		}
	}
	_, err := db.Do("EXEC")
	return err
}

// Del dels data
func (cache *Cache) Del(key *datastore.Key) error {
	if key == nil {
		return nil
	}
	if cache.Skip != nil && cache.Skip(key) {
		return nil
	}

	db := cache.Pool.Get()
	defer db.Close()
	_, err := db.Do("DEL", cache.Prefix+key.String())
	return err
}

// DelMulti dels multi data
func (cache *Cache) DelMulti(keys []*datastore.Key) error {
	db := cache.Pool.Get()
	defer db.Close()
	db.Send("MULTI")
	for _, key := range keys {
		if key == nil {
			continue
		}
		if cache.Skip != nil && cache.Skip(key) {
			continue
		}
		db.Send("DEL", cache.Prefix+key.String())
	}
	_, err := db.Do("EXEC")
	return err
}
<|endoftext|>


<commit_before>package main

/*
Adapted from this tutorial: http://www.learnopengl.com/#!Getting-started/Camera

Shows how to create a basic controllable FPS camera
*/

import (
	"log"
	"runtime"
	"math"

	"github.com/go-gl/gl/v4.1-core/gl"
	"github.com/go-gl/glfw/v3.1/glfw"
	"github.com/go-gl/mathgl/mgl32"

	"github.com/opengl-samples-golang/basic-camera/gfx"
)

const windowWidth = 1280
const windowHeight = 720

func init() {
	// GLFW event handling must be run on the main OS thread
	runtime.LockOSThread()
}

func main() {
	if err := glfw.Init(); err != nil {
		log.Fatalln("failed to inifitialize glfw:", err)
	}
	defer glfw.Terminate()

	glfw.WindowHint(glfw.Resizable, glfw.False)
	glfw.WindowHint(glfw.ContextVersionMajor, 4)
	glfw.WindowHint(glfw.ContextVersionMinor, 1)
	glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
	glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)
	window, err := glfw.CreateWindow(windowWidth, windowHeight, "basic camera", nil, nil)
	if err != nil {
		panic(err)
	}
	window.MakeContextCurrent()

	// Initialize Glow (go function bindings)
	if err := gl.Init(); err != nil {
		panic(err)
	}

	window.SetKeyCallback(keyCallback)

	err = programLoop(window)
	if err != nil {
		log.Fatal(err)
	}
}

/*
 * Creates the Vertex Array Object for a triangle.
 */
func createVAO(vertices []float32, indices []uint32) uint32 {

	var VAO uint32
	gl.GenVertexArrays(1, &VAO)

	var VBO uint32
	gl.GenBuffers(1, &VBO)

	var EBO uint32;
	gl.GenBuffers(1, &EBO)

	// Bind the Vertex Array Object first, then bind and set vertex buffer(s) and attribute pointers()
	gl.BindVertexArray(VAO)

	// copy vertices data into VBO (it needs to be bound first)
	gl.BindBuffer(gl.ARRAY_BUFFER, VBO)
	gl.BufferData(gl.ARRAY_BUFFER, len(vertices)*4, gl.Ptr(vertices), gl.STATIC_DRAW)

	// size of one whole vertex (sum of attrib sizes)
	var stride int32 = 3*4 + 2*4
	var offset int = 0

	// position
	gl.VertexAttribPointer(0, 3, gl.FLOAT, false, stride, gl.PtrOffset(offset))
	gl.EnableVertexAttribArray(0)
	offset += 3*4

	// texture position
	gl.VertexAttribPointer(1, 2, gl.FLOAT, false, stride, gl.PtrOffset(offset))
	gl.EnableVertexAttribArray(1)
	offset += 2*4

	// unbind the VAO (safe practice so we don't accidentally (mis)configure it later)
	gl.BindVertexArray(0)

	return VAO
}

func programLoop(window *glfw.Window) error {

	// the linked shader program determines how the data will be rendered
	vertShader, err := gfx.NewShaderFromFile("shaders/basic.vert", gl.VERTEX_SHADER)
	if err != nil {
		return err
	}

	fragShader, err := gfx.NewShaderFromFile("shaders/basic.frag", gl.FRAGMENT_SHADER)
	if err != nil {
		return err
	}

	program, err := gfx.NewProgram(vertShader, fragShader)
	if err != nil {
		return err
	}
	defer program.Delete()

	vertices := []float32{
		// position        // texture position
		-0.5, -0.5, -0.5,  0.0, 0.0,
		 0.5, -0.5, -0.5,  1.0, 0.0,
		 0.5,  0.5, -0.5,  1.0, 1.0,
		 0.5,  0.5, -0.5,  1.0, 1.0,
		-0.5,  0.5, -0.5,  0.0, 1.0,
		-0.5, -0.5, -0.5,  0.0, 0.0,

		-0.5, -0.5,  0.5,  0.0, 0.0,
		 0.5, -0.5,  0.5,  1.0, 0.0,
		 0.5,  0.5,  0.5,  1.0, 1.0,
		 0.5,  0.5,  0.5,  1.0, 1.0,
		-0.5,  0.5,  0.5,  0.0, 1.0,
		-0.5, -0.5,  0.5,  0.0, 0.0,

		-0.5,  0.5,  0.5,  1.0, 0.0,
		-0.5,  0.5, -0.5,  1.0, 1.0,
		-0.5, -0.5, -0.5,  0.0, 1.0,
		-0.5, -0.5, -0.5,  0.0, 1.0,
		-0.5, -0.5,  0.5,  0.0, 0.0,
		-0.5,  0.5,  0.5,  1.0, 0.0,

		 0.5,  0.5,  0.5,  1.0, 0.0,
		 0.5,  0.5, -0.5,  1.0, 1.0,
		 0.5, -0.5, -0.5,  0.0, 1.0,
		 0.5, -0.5, -0.5,  0.0, 1.0,
		 0.5, -0.5,  0.5,  0.0, 0.0,
		 0.5,  0.5,  0.5,  1.0, 0.0,

		-0.5, -0.5, -0.5,  0.0, 1.0,
		 0.5, -0.5, -0.5,  1.0, 1.0,
		 0.5, -0.5,  0.5,  1.0, 0.0,
		 0.5, -0.5,  0.5,  1.0, 0.0,
		-0.5, -0.5,  0.5,  0.0, 0.0,
		-0.5, -0.5, -0.5,  0.0, 1.0,

		-0.5,  0.5, -0.5,  0.0, 1.0,
		 0.5,  0.5, -0.5,  1.0, 1.0,
		 0.5,  0.5,  0.5,  1.0, 0.0,
		 0.5,  0.5,  0.5,  1.0, 0.0,
		-0.5,  0.5,  0.5,  0.0, 0.0,
		-0.5,  0.5, -0.5,  0.0, 1.0,
	}

	indices := []uint32{}

	VAO := createVAO(vertices, indices)
	texture0, err := gfx.NewTextureFromFile("../images/RTS_Crate.png",
	                                        gl.CLAMP_TO_EDGE, gl.CLAMP_TO_EDGE)
	if err != nil {
		panic(err.Error())
	}

	texture1, err := gfx.NewTextureFromFile("../images/trollface-transparent.png",
	                                        gl.CLAMP_TO_EDGE, gl.CLAMP_TO_EDGE)
	if err != nil {
		panic(err.Error())
	}

	cubePositions := [][]float32 {
		[]float32{ 0.0,  0.0,  -3.0 },
		[]float32{ 2.0,  5.0, -15.0},
		[]float32{-1.5, -2.2, -2.5 },
		[]float32{-3.8, -2.0, -12.3},
		[]float32{ 2.4, -0.4, -3.5 },
		[]float32{-1.7,  3.0, -7.5 },
		[]float32{ 1.3, -2.0, -2.5 },
		[]float32{ 1.5,  2.0, -2.5 },
		[]float32{ 1.5,  0.2, -1.5 },
		[]float32{-1.3,  1.0, -1.5 },
	}

	gl.Enable(gl.DEPTH_TEST)

	for !window.ShouldClose() {
		// poll events and call their registered callbacks
		glfw.PollEvents()

		// background color
		gl.ClearColor(0.2, 0.5, 0.5, 1.0)
		gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)

		program.Use()

		// bind textures
		texture0.Bind(gl.TEXTURE0)
		texture0.SetUniform(program.GetUniformLocation("ourTexture0"))

		texture1.Bind(gl.TEXTURE1)
		texture1.SetUniform(program.GetUniformLocation("ourTexture1"))

		// cube rotation matrices
		rotateX   := (mgl32.Rotate3DX(mgl32.DegToRad(-60 * float32(glfw.GetTime()))))
		rotateY   := (mgl32.Rotate3DY(mgl32.DegToRad(-60 * float32(glfw.GetTime()))))
		rotateZ   := (mgl32.Rotate3DZ(mgl32.DegToRad(-60 * float32(glfw.GetTime()))))

		// creates perspective
		projectTransform := mgl32.Perspective(mgl32.DegToRad(60), windowWidth/windowHeight, 0.1, 100.0)

		// Calculate camera transform matrix for a rotating camera focusing on the origin
		// x/z are horizontal, y is vertical
		var cameraRadius float32 = 10.0
		cameraPos := mgl32.Vec3{
			cameraRadius*float32(math.Sin(glfw.GetTime())),
			0,
			cameraRadius*float32(math.Cos(glfw.GetTime())),
		}
		cameraTarget := mgl32.Vec3{0, 0, 0}

		up := mgl32.Vec3{0, 1, 0}

		cameraTransform := mgl32.LookAt(
			cameraPos.X(), cameraPos.Y(), cameraPos.Z(),
			cameraTarget.X(), cameraTarget.Y(), cameraTarget.Z(),
			up.X(), up.Y(), up.Z(),
		)

		gl.UniformMatrix4fv(program.GetUniformLocation("camera"), 1, false, &cameraTransform[0])
		gl.UniformMatrix4fv(program.GetUniformLocation("project"), 1, false,
		&projectTransform[0])

		gl.BindVertexArray(VAO)

		// draw each cube after all coordinate system transforms are bound
		for _, pos := range cubePositions {
			worldTranslate := mgl32.Translate3D(pos[0], pos[1], pos[2])
			worldTransform := (worldTranslate.Mul4(rotateX.Mul3(rotateY).Mul3(rotateZ).Mat4()))

			gl.UniformMatrix4fv(program.GetUniformLocation("world"), 1, false,
			                    &worldTransform[0])

			gl.DrawArrays(gl.TRIANGLES, 0, 36)
		}

		gl.BindVertexArray(0)

		texture0.UnBind()
		texture1.UnBind()

		// end of draw loop

		// swap in the rendered buffer
		window.SwapBuffers()
	}

	return nil
}

func keyCallback(window *glfw.Window, key glfw.Key, scancode int, action glfw.Action,
	mods glfw.ModifierKey) {

	// When a user presses the escape key, we set the WindowShouldClose property to true,
	// which closes the application
	if key == glfw.KeyEscape && action == glfw.Press {
		window.SetShouldClose(true)
	}
}
<commit_msg>cleaning up basic-camera so far<commit_after>package main

/*
Adapted from this tutorial: http://www.learnopengl.com/#!Getting-started/Camera

Shows how to create a basic controllable FPS camera
*/

import (
	"log"
	"runtime"
	"math"

	"github.com/go-gl/gl/v4.1-core/gl"
	"github.com/go-gl/glfw/v3.1/glfw"
	"github.com/go-gl/mathgl/mgl32"

	"github.com/opengl-samples-golang/basic-camera/gfx"
)

const windowWidth = 1280
const windowHeight = 720

// vertices to draw 6 faces of a cube
var cubeVertices = []float32{
	// position        // texture position
	-0.5, -0.5, -0.5,  0.0, 0.0,
	 0.5, -0.5, -0.5,  1.0, 0.0,
	 0.5,  0.5, -0.5,  1.0, 1.0,
	 0.5,  0.5, -0.5,  1.0, 1.0,
	-0.5,  0.5, -0.5,  0.0, 1.0,
	-0.5, -0.5, -0.5,  0.0, 0.0,

	-0.5, -0.5,  0.5,  0.0, 0.0,
	 0.5, -0.5,  0.5,  1.0, 0.0,
	 0.5,  0.5,  0.5,  1.0, 1.0,
	 0.5,  0.5,  0.5,  1.0, 1.0,
	-0.5,  0.5,  0.5,  0.0, 1.0,
	-0.5, -0.5,  0.5,  0.0, 0.0,

	-0.5,  0.5,  0.5,  1.0, 0.0,
	-0.5,  0.5, -0.5,  1.0, 1.0,
	-0.5, -0.5, -0.5,  0.0, 1.0,
	-0.5, -0.5, -0.5,  0.0, 1.0,
	-0.5, -0.5,  0.5,  0.0, 0.0,
	-0.5,  0.5,  0.5,  1.0, 0.0,

	 0.5,  0.5,  0.5,  1.0, 0.0,
	 0.5,  0.5, -0.5,  1.0, 1.0,
	 0.5, -0.5, -0.5,  0.0, 1.0,
	 0.5, -0.5, -0.5,  0.0, 1.0,
	 0.5, -0.5,  0.5,  0.0, 0.0,
	 0.5,  0.5,  0.5,  1.0, 0.0,

	-0.5, -0.5, -0.5,  0.0, 1.0,
	 0.5, -0.5, -0.5,  1.0, 1.0,
	 0.5, -0.5,  0.5,  1.0, 0.0,
	 0.5, -0.5,  0.5,  1.0, 0.0,
	-0.5, -0.5,  0.5,  0.0, 0.0,
	-0.5, -0.5, -0.5,  0.0, 1.0,

	-0.5,  0.5, -0.5,  0.0, 1.0,
	 0.5,  0.5, -0.5,  1.0, 1.0,
	 0.5,  0.5,  0.5,  1.0, 0.0,
	 0.5,  0.5,  0.5,  1.0, 0.0,
	-0.5,  0.5,  0.5,  0.0, 0.0,
	-0.5,  0.5, -0.5,  0.0, 1.0,
}

var cubePositions = [][]float32 {
	{ 0.0,  0.0,  -3.0},
	{ 2.0,  5.0, -15.0},
	{-1.5, -2.2, -2.5 },
	{-3.8, -2.0, -12.3},
	{ 2.4, -0.4, -3.5 },
	{-1.7,  3.0, -7.5 },
	{ 1.3, -2.0, -2.5 },
	{ 1.5,  2.0, -2.5 },
	{ 1.5,  0.2, -1.5 },
	{-1.3,  1.0, -1.5 },
}

func init() {
	// GLFW event handling must be run on the main OS thread
	runtime.LockOSThread()
}

func main() {
	if err := glfw.Init(); err != nil {
		log.Fatalln("failed to inifitialize glfw:", err)
	}
	defer glfw.Terminate()

	glfw.WindowHint(glfw.Resizable, glfw.False)
	glfw.WindowHint(glfw.ContextVersionMajor, 4)
	glfw.WindowHint(glfw.ContextVersionMinor, 1)
	glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
	glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)
	window, err := glfw.CreateWindow(windowWidth, windowHeight, "basic camera", nil, nil)
	if err != nil {
		panic(err)
	}
	window.MakeContextCurrent()

	// Initialize Glow (go function bindings)
	if err := gl.Init(); err != nil {
		panic(err)
	}

	window.SetKeyCallback(keyCallback)

	err = programLoop(window)
	if err != nil {
		log.Fatal(err)
	}
}

/*
 * Creates the Vertex Array Object for a triangle.
 * indices is leftover from earlier samples and not used here.
 */
func createVAO(vertices []float32, indices []uint32) uint32 {

	var VAO uint32
	gl.GenVertexArrays(1, &VAO)

	var VBO uint32
	gl.GenBuffers(1, &VBO)

	var EBO uint32;
	gl.GenBuffers(1, &EBO)

	// Bind the Vertex Array Object first, then bind and set vertex buffer(s) and attribute pointers()
	gl.BindVertexArray(VAO)

	// copy vertices data into VBO (it needs to be bound first)
	gl.BindBuffer(gl.ARRAY_BUFFER, VBO)
	gl.BufferData(gl.ARRAY_BUFFER, len(vertices)*4, gl.Ptr(vertices), gl.STATIC_DRAW)

	// size of one whole vertex (sum of attrib sizes)
	var stride int32 = 3*4 + 2*4
	var offset int = 0

	// position
	gl.VertexAttribPointer(0, 3, gl.FLOAT, false, stride, gl.PtrOffset(offset))
	gl.EnableVertexAttribArray(0)
	offset += 3*4

	// texture position
	gl.VertexAttribPointer(1, 2, gl.FLOAT, false, stride, gl.PtrOffset(offset))
	gl.EnableVertexAttribArray(1)
	offset += 2*4

	// unbind the VAO (safe practice so we don't accidentally (mis)configure it later)
	gl.BindVertexArray(0)

	return VAO
}

func programLoop(window *glfw.Window) error {

	// the linked shader program determines how the data will be rendered
	vertShader, err := gfx.NewShaderFromFile("shaders/basic.vert", gl.VERTEX_SHADER)
	if err != nil {
		return err
	}

	fragShader, err := gfx.NewShaderFromFile("shaders/basic.frag", gl.FRAGMENT_SHADER)
	if err != nil {
		return err
	}

	program, err := gfx.NewProgram(vertShader, fragShader)
	if err != nil {
		return err
	}
	defer program.Delete()

	VAO := createVAO(cubeVertices, nil)
	texture0, err := gfx.NewTextureFromFile("../images/RTS_Crate.png",
	                                        gl.CLAMP_TO_EDGE, gl.CLAMP_TO_EDGE)
	if err != nil {
		panic(err.Error())
	}

	texture1, err := gfx.NewTextureFromFile("../images/trollface-transparent.png",
	                                        gl.CLAMP_TO_EDGE, gl.CLAMP_TO_EDGE)
	if err != nil {
		panic(err.Error())
	}

	// ensure that triangles that are "behind" others do not draw over top of them
	gl.Enable(gl.DEPTH_TEST)

	for !window.ShouldClose() {
		// poll events and call their registered callbacks
		glfw.PollEvents()

		// background color
		gl.ClearColor(0.2, 0.5, 0.5, 1.0)
		gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)  // depth buffer needed for DEPTH_TEST

		program.Use()

		// bind textures
		texture0.Bind(gl.TEXTURE0)
		texture0.SetUniform(program.GetUniformLocation("ourTexture0"))

		texture1.Bind(gl.TEXTURE1)
		texture1.SetUniform(program.GetUniformLocation("ourTexture1"))

		// cube rotation matrices
		rotateX   := (mgl32.Rotate3DX(mgl32.DegToRad(-60 * float32(glfw.GetTime()))))
		rotateY   := (mgl32.Rotate3DY(mgl32.DegToRad(-60 * float32(glfw.GetTime()))))
		rotateZ   := (mgl32.Rotate3DZ(mgl32.DegToRad(-60 * float32(glfw.GetTime()))))

		// creates perspective
		fov := float32(60.0)
		projectTransform := mgl32.Perspective(mgl32.DegToRad(fov), windowWidth/windowHeight, 0.1, 100.0)

		// Calculate camera transform matrix for a rotating camera focusing on the origin
		// x/z are horizontal, y is vertical
		var cameraRadius float32 = 10.0
		cameraPos := mgl32.Vec3{
			cameraRadius*float32(math.Sin(glfw.GetTime())),
			0,
			cameraRadius*float32(math.Cos(glfw.GetTime())),
		}
		cameraTarget := mgl32.Vec3{0, 0, 0}

		up := mgl32.Vec3{0, 1, 0}

		cameraTransform := mgl32.LookAt(
			cameraPos.X(), cameraPos.Y(), cameraPos.Z(),
			cameraTarget.X(), cameraTarget.Y(), cameraTarget.Z(),
			up.X(), up.Y(), up.Z(),
		)

		gl.UniformMatrix4fv(program.GetUniformLocation("camera"), 1, false, &cameraTransform[0])
		gl.UniformMatrix4fv(program.GetUniformLocation("project"), 1, false,
		&projectTransform[0])

		gl.BindVertexArray(VAO)

		// draw each cube after all coordinate system transforms are bound
		for _, pos := range cubePositions {
			worldTranslate := mgl32.Translate3D(pos[0], pos[1], pos[2])
			worldTransform := (worldTranslate.Mul4(rotateX.Mul3(rotateY).Mul3(rotateZ).Mat4()))

			gl.UniformMatrix4fv(program.GetUniformLocation("world"), 1, false,
			                    &worldTransform[0])

			gl.DrawArrays(gl.TRIANGLES, 0, 36)
		}

		gl.BindVertexArray(0)

		texture0.UnBind()
		texture1.UnBind()

		// end of draw loop

		// swap in the rendered buffer
		window.SwapBuffers()
	}

	return nil
}

func keyCallback(window *glfw.Window, key glfw.Key, scancode int, action glfw.Action,
	mods glfw.ModifierKey) {

	// When a user presses the escape key, we set the WindowShouldClose property to true,
	// which closes the application
	if key == glfw.KeyEscape && action == glfw.Press {
		window.SetShouldClose(true)
	}
}
<|endoftext|>


<commit_before>package backend

import (
	"bytes"
	"database/sql"
	"encoding/json"
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"

	_ "github.com/jbarham/gopgsqldriver"
	"github.com/zimmski/tirion"
)

type Postgresql struct {
	Db *sql.DB
}

func (p *Postgresql) Init() error {
	var err error

	p.Db, err = sql.Open("postgres", "user=zimmski dbname=tirion sslmode=disable")

	if err != nil {
		panic(fmt.Sprintf("Cannot connect to database: %v", err))
	}

	err = p.Db.Ping()

	if err != nil {
		panic(fmt.Sprintf("Cannot ping database: %v", err))
	}

	p.Db.SetMaxIdleConns(100)

	return nil
}

func (p *Postgresql) SearchPrograms() ([]tirion.Program, error) {
	tx, err := p.Db.Begin()

	if err != nil {
		return nil, err
	}

	programs := make([]tirion.Program, 0)

	rows, err := tx.Query("SELECT name FROM run GROUP BY name ORDER BY name")

	if err != nil {
		return nil, err
	}

	defer rows.Close()

	for rows.Next() {
		var program = tirion.Program{}

		if err := rows.Scan(&program.Name); err != nil {
			return nil, err
		}

		programs = append(programs, program)
	}

	if err := rows.Err(); err != nil {
		return nil, err
	}

	err = tx.Commit()

	if err != nil {
		return nil, err
	}

	return programs, nil
}

func (p *Postgresql) FindRun(programName string, runId int) (*tirion.Run, error) {
	tx, err := p.Db.Begin()

	if err != nil {
		return nil, err
	}

	row := tx.QueryRow("SELECT id, name, sub_name, interval, metrics, prog, prog_arguments, extract(epoch from start), extract(epoch from stop) FROM run WHERE name = $1 and id = $2", programName, runId)

	var run = tirion.Run{}
	var metrics, start string
	var stop *string

	if err := row.Scan(&run.Id, &run.Name, &run.SubName, &run.Interval, &metrics, &run.Prog, &run.ProgArguments, &start, &stop); err != nil {
		if err == sql.ErrNoRows {
			return nil, nil
		} else {
			return nil, err
		}
	}

	json.Unmarshal([]byte(metrics), &run.Metrics)

	var sta, _ = strconv.ParseFloat(start, 64)
	var stat = time.Unix(int64(sta), 0)
	run.Start = &stat

	if stop != nil {
		var sto, _ = strconv.ParseFloat(*stop, 64)
		var stot = time.Unix(int64(sto), 0)
		run.Stop = &stot
	} else {
		run.Stop = nil
	}

	err = tx.Commit()

	if err != nil {
		return nil, err
	}

	return &run, nil
}
func (p *Postgresql) SearchRuns(programName string) ([]tirion.Run, error) {
	tx, err := p.Db.Begin()

	if err != nil {
		return nil, err
	}

	runs := make([]tirion.Run, 0)

	rows, err := tx.Query("SELECT id, name, sub_name, interval, prog, prog_arguments, extract(epoch from start), extract(epoch from stop) FROM run WHERE name = $1 ORDER BY start desc", programName)

	if err != nil {
		return nil, err
	}

	defer rows.Close()

	for rows.Next() {
		var run = tirion.Run{}

		var start, stop *string

		if err := rows.Scan(&run.Id, &run.Name, &run.SubName, &run.Interval, &run.Prog, &run.ProgArguments, &start, &stop); err != nil {
			return nil, err
		}

		var sta, _ = strconv.ParseFloat(*start, 64)
		var stat = time.Unix(int64(sta), 0)
		run.Start = &stat

		if stop != nil {
			var sto, _ = strconv.ParseFloat(*stop, 64)
			var stot = time.Unix(int64(sto), 0)
			run.Stop = &stot
		} else {
			run.Stop = nil
		}

		runs = append(runs, run)
	}

	if err := rows.Err(); err != nil {
		return nil, err
	}

	err = tx.Commit()

	if err != nil {
		return nil, err
	}

	return runs, nil
}
func (p *Postgresql) StartRun(run *tirion.Run) error {
	tx, err := p.Db.Begin()

	if err != nil {
		return err
	}

	var metrics, _ = json.Marshal(run.Metrics)

	err = tx.QueryRow("INSERT INTO run(name, sub_name, interval, metrics, prog, prog_arguments, start) VALUES($1, $2, $3, $4, $5, $6, CURRENT_TIMESTAMP) RETURNING id", run.Name, run.SubName, run.Interval, string(metrics), run.Prog, run.ProgArguments).Scan(&run.Id)

	if err != nil {
		return err
	}

	var columns = make([]string, len(run.Metrics))

	for i, m := range run.Metrics {
		var n = strings.Replace(m.Name, ".", "_", -1)

		switch m.Type {
		case "float":
			columns[i] = n + " REAL NOT NULL"
		default:
			columns[i] = n + " " + m.Type + " NOT NULL"
		}
	}

	_, err = tx.Exec("CREATE TABLE r" + strconv.FormatInt(int64(run.Id), 10) + "(t TIMESTAMP NOT NULL, " + strings.Join(columns, ",") + ", PRIMARY KEY(t))")

	if err != nil {
		return err
	}

	_, err = tx.Exec("CREATE TABLE rt" + strconv.FormatInt(int64(run.Id), 10) + "(t TIMESTAMP NOT NULL, message TEXT NOT NULL, PRIMARY KEY(t))")

	if err != nil {
		return err
	}

	err = tx.Commit()

	if err != nil {
		return err
	}

	return nil
}
func (p *Postgresql) StopRun(runId int) error {
	tx, err := p.Db.Begin()

	if err != nil {
		return err
	}

	rows, err := tx.Query("SELECT id FROM run WHERE id = $1", runId)

	if err != nil {
		panic(err)
	} else if !rows.Next() {
		panic(errors.New("Cannot find run"))
	}

	defer rows.Close()

	_, err = tx.Exec("UPDATE run SET stop = CURRENT_TIMESTAMP WHERE id = $1", runId)

	if err != nil {
		panic(err)
	}

	err = tx.Commit()

	if err != nil {
		return err
	}

	return nil
}

func (p *Postgresql) CreateMetrics(runId int, metrics []tirion.MessageData) error {
	tx, err := p.Db.Begin()

	if err != nil {
		return err
	}

	rows, err := tx.Query("SELECT id FROM run WHERE id = $1", runId)

	if err != nil {
		panic(err)
	} else if !rows.Next() {
		panic(errors.New("Cannot find run"))
	}

	defer rows.Close()

	for _, m := range metrics {
		var ffff bytes.Buffer

		ffff.WriteString("INSERT INTO r" + strconv.FormatInt(int64(runId), 10) + " VALUES(TO_TIMESTAMP($1)")

		for _, i := range m.Data {
			ffff.WriteString("," + strconv.FormatFloat(float64(i), 'f', 5, 32))
		}

		ffff.WriteString(")")

		_, err = tx.Exec(ffff.String(), float64(m.Time.UnixNano())/1000000000.0)

		if err != nil {
			return err
		}
	}

	err = tx.Commit()

	if err != nil {
		return err
	}

	return nil
}
func (p *Postgresql) SearchMetricOfRun(run *tirion.Run, metricName string) ([][]interface{}, error) {
	var found = false

	for _, m := range run.Metrics {
		if m.Name == metricName {
			found = true

			break
		}
	}

	if !found {
		return nil, errors.New("metric name not found")
	}

	tx, err := p.Db.Begin()

	if err != nil {
		return nil, err
	}

	metrics := make([][]interface{}, 0)

	rows, err := tx.Query("SELECT EXTRACT(EPOCH FROM t) * 1000.0, " + strings.Replace(metricName, ".", "_", -1) + " FROM r" + strconv.FormatInt(int64(run.Id), 10) + " ORDER BY t")

	if err != nil {
		return nil, err
	}

	defer rows.Close()

	for rows.Next() {
		var metric = make([]interface{}, 2)

		var m float32
		var tt float64

		if err := rows.Scan(&tt, &m); err != nil {
			return nil, err
		}

		var t = int64(tt)

		metric[0] = &t
		metric[1] = &m

		metrics = append(metrics, metric)
	}

	if err := rows.Err(); err != nil {
		return nil, err
	}

	err = tx.Commit()

	if err != nil {
		return nil, err
	}

	return metrics, nil
}
func (p *Postgresql) SearchMetricsOfRun(run *tirion.Run) ([][]float32, error) {
	tx, err := p.Db.Begin()

	if err != nil {
		return nil, err
	}

	pointers := make([]interface{}, len(run.Metrics)+1)
	metrics := make([][]float32, 0)

	var t string

	rows, err := tx.Query("SELECT * FROM r" + strconv.FormatInt(int64(run.Id), 10) + " ORDER BY t")

	if err != nil {
		return nil, err
	}

	defer rows.Close()

	for rows.Next() {
		var metric = make([]float32, len(run.Metrics)+1)

		for i := range pointers {
			pointers[i] = &metric[i]
		}

		pointers[0] = &t

		if err := rows.Scan(pointers...); err != nil {
			return nil, err
		}

		tt, err := time.Parse("2006-01-02 15:04:05.9999", t)

		if err != nil {
			return nil, err
		}

		metric[0] = float32(tt.UnixNano()) / 1000000000.0

		metrics = append(metrics, metric)
	}

	if err := rows.Err(); err != nil {
		return nil, err
	}

	err = tx.Commit()

	if err != nil {
		return nil, err
	}

	return metrics, nil
}

func (p *Postgresql) CreateTag(runId int, tag *tirion.Tag) error {
	tx, err := p.Db.Begin()

	if err != nil {
		return err
	}

	rows, err := tx.Query("SELECT id FROM run WHERE id = $1", runId)

	if err != nil {
		panic(err)
	} else if !rows.Next() {
		panic(errors.New("Cannot find run"))
	}

	defer rows.Close()

	_, err = tx.Exec("INSERT INTO rt"+strconv.FormatInt(int64(runId), 10)+"(t, message) VALUES(TO_TIMESTAMP($1), $2)", float64(tag.Time.UnixNano())/1000000000.0, tag.Tag)

	if err != nil {
		panic(err)
	}

	err = tx.Commit()

	if err != nil {
		return err
	}

	return nil
}

func (p *Postgresql) SearchTagsOfRun(run *tirion.Run) ([]tirion.HighStockTag, error) {
	tx, err := p.Db.Begin()

	if err != nil {
		return nil, err
	}

	tags := make([]tirion.HighStockTag, 0)

	rows, err := tx.Query("SELECT EXTRACT(EPOCH FROM t) * 1000.0, message FROM rt" + strconv.FormatInt(int64(run.Id), 10) + " ORDER BY t")

	if err != nil {
		return nil, err
	}

	defer rows.Close()

	for rows.Next() {
		var tag = new(tirion.HighStockTag)

		var m string
		var tt float64

		if err := rows.Scan(&tt, &m); err != nil {
			return nil, err
		}

		tag.X = int64(tt)
		tag.Title = m

		tags = append(tags, *tag)
	}

	if err := rows.Err(); err != nil {
		return nil, err
	}

	err = tx.Commit()

	if err != nil {
		return nil, err
	}

	return tags, nil
}
<commit_msg>handle no rows case for multi row selects<commit_after>package backend

import (
	"bytes"
	"database/sql"
	"encoding/json"
	"errors"
	"fmt"
	"strconv"
	"strings"
	"time"

	_ "github.com/jbarham/gopgsqldriver"
	"github.com/zimmski/tirion"
)

type Postgresql struct {
	Db *sql.DB
}

func (p *Postgresql) Init() error {
	var err error

	p.Db, err = sql.Open("postgres", "user=zimmski dbname=tirion sslmode=disable")

	if err != nil {
		panic(fmt.Sprintf("Cannot connect to database: %v", err))
	}

	err = p.Db.Ping()

	if err != nil {
		panic(fmt.Sprintf("Cannot ping database: %v", err))
	}

	p.Db.SetMaxIdleConns(100)

	return nil
}

func (p *Postgresql) SearchPrograms() ([]tirion.Program, error) {
	tx, err := p.Db.Begin()

	if err != nil {
		return nil, err
	}

	programs := make([]tirion.Program, 0)

	rows, err := tx.Query("SELECT name FROM run GROUP BY name ORDER BY name")

	if err != nil {
		return nil, err
	}

	defer rows.Close()

	for rows.Next() {
		var program = tirion.Program{}

		if err := rows.Scan(&program.Name); err != nil {
			return nil, err
		}

		programs = append(programs, program)
	}

	if err := rows.Err(); err != nil && err != sql.ErrNoRows {
		return nil, err
	}

	err = tx.Commit()

	if err != nil {
		return nil, err
	}

	return programs, nil
}

func (p *Postgresql) FindRun(programName string, runId int) (*tirion.Run, error) {
	tx, err := p.Db.Begin()

	if err != nil {
		return nil, err
	}

	row := tx.QueryRow("SELECT id, name, sub_name, interval, metrics, prog, prog_arguments, extract(epoch from start), extract(epoch from stop) FROM run WHERE name = $1 and id = $2", programName, runId)

	var run = tirion.Run{}
	var metrics, start string
	var stop *string

	if err := row.Scan(&run.Id, &run.Name, &run.SubName, &run.Interval, &metrics, &run.Prog, &run.ProgArguments, &start, &stop); err != nil {
		if err == sql.ErrNoRows {
			return nil, nil
		} else {
			return nil, err
		}
	}

	json.Unmarshal([]byte(metrics), &run.Metrics)

	var sta, _ = strconv.ParseFloat(start, 64)
	var stat = time.Unix(int64(sta), 0)
	run.Start = &stat

	if stop != nil {
		var sto, _ = strconv.ParseFloat(*stop, 64)
		var stot = time.Unix(int64(sto), 0)
		run.Stop = &stot
	} else {
		run.Stop = nil
	}

	err = tx.Commit()

	if err != nil {
		return nil, err
	}

	return &run, nil
}
func (p *Postgresql) SearchRuns(programName string) ([]tirion.Run, error) {
	tx, err := p.Db.Begin()

	if err != nil {
		return nil, err
	}

	runs := make([]tirion.Run, 0)

	rows, err := tx.Query("SELECT id, name, sub_name, interval, prog, prog_arguments, extract(epoch from start), extract(epoch from stop) FROM run WHERE name = $1 ORDER BY start desc", programName)

	if err != nil {
		return nil, err
	}

	defer rows.Close()

	for rows.Next() {
		var run = tirion.Run{}

		var start, stop *string

		if err := rows.Scan(&run.Id, &run.Name, &run.SubName, &run.Interval, &run.Prog, &run.ProgArguments, &start, &stop); err != nil {
			return nil, err
		}

		var sta, _ = strconv.ParseFloat(*start, 64)
		var stat = time.Unix(int64(sta), 0)
		run.Start = &stat

		if stop != nil {
			var sto, _ = strconv.ParseFloat(*stop, 64)
			var stot = time.Unix(int64(sto), 0)
			run.Stop = &stot
		} else {
			run.Stop = nil
		}

		runs = append(runs, run)
	}

	if err := rows.Err(); err != nil && err != sql.ErrNoRows {
		return nil, err
	}

	err = tx.Commit()

	if err != nil {
		return nil, err
	}

	return runs, nil
}
func (p *Postgresql) StartRun(run *tirion.Run) error {
	tx, err := p.Db.Begin()

	if err != nil {
		return err
	}

	var metrics, _ = json.Marshal(run.Metrics)

	err = tx.QueryRow("INSERT INTO run(name, sub_name, interval, metrics, prog, prog_arguments, start) VALUES($1, $2, $3, $4, $5, $6, CURRENT_TIMESTAMP) RETURNING id", run.Name, run.SubName, run.Interval, string(metrics), run.Prog, run.ProgArguments).Scan(&run.Id)

	if err != nil {
		return err
	}

	var columns = make([]string, len(run.Metrics))

	for i, m := range run.Metrics {
		var n = strings.Replace(m.Name, ".", "_", -1)

		switch m.Type {
		case "float":
			columns[i] = n + " REAL NOT NULL"
		default:
			columns[i] = n + " " + m.Type + " NOT NULL"
		}
	}

	_, err = tx.Exec("CREATE TABLE r" + strconv.FormatInt(int64(run.Id), 10) + "(t TIMESTAMP NOT NULL, " + strings.Join(columns, ",") + ", PRIMARY KEY(t))")

	if err != nil {
		return err
	}

	_, err = tx.Exec("CREATE TABLE rt" + strconv.FormatInt(int64(run.Id), 10) + "(t TIMESTAMP NOT NULL, message TEXT NOT NULL, PRIMARY KEY(t))")

	if err != nil {
		return err
	}

	err = tx.Commit()

	if err != nil {
		return err
	}

	return nil
}
func (p *Postgresql) StopRun(runId int) error {
	tx, err := p.Db.Begin()

	if err != nil {
		return err
	}

	rows, err := tx.Query("SELECT id FROM run WHERE id = $1", runId)

	if err != nil {
		panic(err)
	} else if !rows.Next() {
		panic(errors.New("Cannot find run"))
	}

	defer rows.Close()

	_, err = tx.Exec("UPDATE run SET stop = CURRENT_TIMESTAMP WHERE id = $1", runId)

	if err != nil {
		panic(err)
	}

	err = tx.Commit()

	if err != nil {
		return err
	}

	return nil
}

func (p *Postgresql) CreateMetrics(runId int, metrics []tirion.MessageData) error {
	tx, err := p.Db.Begin()

	if err != nil {
		return err
	}

	rows, err := tx.Query("SELECT id FROM run WHERE id = $1", runId)

	if err != nil {
		panic(err)
	} else if !rows.Next() {
		panic(errors.New("Cannot find run"))
	}

	defer rows.Close()

	for _, m := range metrics {
		var ffff bytes.Buffer

		ffff.WriteString("INSERT INTO r" + strconv.FormatInt(int64(runId), 10) + " VALUES(TO_TIMESTAMP($1)")

		for _, i := range m.Data {
			ffff.WriteString("," + strconv.FormatFloat(float64(i), 'f', 5, 32))
		}

		ffff.WriteString(")")

		_, err = tx.Exec(ffff.String(), float64(m.Time.UnixNano())/1000000000.0)

		if err != nil {
			return err
		}
	}

	err = tx.Commit()

	if err != nil {
		return err
	}

	return nil
}
func (p *Postgresql) SearchMetricOfRun(run *tirion.Run, metricName string) ([][]interface{}, error) {
	var found = false

	for _, m := range run.Metrics {
		if m.Name == metricName {
			found = true

			break
		}
	}

	if !found {
		return nil, errors.New("metric name not found")
	}

	tx, err := p.Db.Begin()

	if err != nil {
		return nil, err
	}

	metrics := make([][]interface{}, 0)

	rows, err := tx.Query("SELECT EXTRACT(EPOCH FROM t) * 1000.0, " + strings.Replace(metricName, ".", "_", -1) + " FROM r" + strconv.FormatInt(int64(run.Id), 10) + " ORDER BY t")

	if err != nil {
		return nil, err
	}

	defer rows.Close()

	for rows.Next() {
		var metric = make([]interface{}, 2)

		var m float32
		var tt float64

		if err := rows.Scan(&tt, &m); err != nil {
			return nil, err
		}

		var t = int64(tt)

		metric[0] = &t
		metric[1] = &m

		metrics = append(metrics, metric)
	}

	if err := rows.Err(); err != nil && err != sql.ErrNoRows {
		return nil, err
	}

	err = tx.Commit()

	if err != nil {
		return nil, err
	}

	return metrics, nil
}
func (p *Postgresql) SearchMetricsOfRun(run *tirion.Run) ([][]float32, error) {
	tx, err := p.Db.Begin()

	if err != nil {
		return nil, err
	}

	pointers := make([]interface{}, len(run.Metrics)+1)
	metrics := make([][]float32, 0)

	var t string

	rows, err := tx.Query("SELECT * FROM r" + strconv.FormatInt(int64(run.Id), 10) + " ORDER BY t")

	if err != nil {
		return nil, err
	}

	defer rows.Close()

	for rows.Next() {
		var metric = make([]float32, len(run.Metrics)+1)

		for i := range pointers {
			pointers[i] = &metric[i]
		}

		pointers[0] = &t

		if err := rows.Scan(pointers...); err != nil {
			return nil, err
		}

		tt, err := time.Parse("2006-01-02 15:04:05.9999", t)

		if err != nil {
			return nil, err
		}

		metric[0] = float32(tt.UnixNano()) / 1000000000.0

		metrics = append(metrics, metric)
	}

	if err := rows.Err(); err != nil && err != sql.ErrNoRows {
		return nil, err
	}

	err = tx.Commit()

	if err != nil {
		return nil, err
	}

	return metrics, nil
}

func (p *Postgresql) CreateTag(runId int, tag *tirion.Tag) error {
	tx, err := p.Db.Begin()

	if err != nil {
		return err
	}

	rows, err := tx.Query("SELECT id FROM run WHERE id = $1", runId)

	if err != nil {
		panic(err)
	} else if !rows.Next() {
		panic(errors.New("Cannot find run"))
	}

	defer rows.Close()

	_, err = tx.Exec("INSERT INTO rt"+strconv.FormatInt(int64(runId), 10)+"(t, message) VALUES(TO_TIMESTAMP($1), $2)", float64(tag.Time.UnixNano())/1000000000.0, tag.Tag)

	if err != nil {
		panic(err)
	}

	err = tx.Commit()

	if err != nil {
		return err
	}

	return nil
}

func (p *Postgresql) SearchTagsOfRun(run *tirion.Run) ([]tirion.HighStockTag, error) {
	tx, err := p.Db.Begin()

	if err != nil {
		return nil, err
	}

	tags := make([]tirion.HighStockTag, 0)

	rows, err := tx.Query("SELECT EXTRACT(EPOCH FROM t) * 1000.0, message FROM rt" + strconv.FormatInt(int64(run.Id), 10) + " ORDER BY t")

	if err != nil {
		return nil, err
	}

	defer rows.Close()

	for rows.Next() {
		var tag = new(tirion.HighStockTag)

		var m string
		var tt float64

		if err := rows.Scan(&tt, &m); err != nil {
			return nil, err
		}

		tag.X = int64(tt)
		tag.Title = m

		tags = append(tags, *tag)
	}

	if err := rows.Err(); err != nil && err != sql.ErrNoRows {
		return nil, err
	}

	err = tx.Commit()

	if err != nil {
		return nil, err
	}

	return tags, nil
}
<|endoftext|>


<commit_before><commit_msg>Do not wrap ErrDead in updateSupportedContainers<commit_after><|endoftext|>


<commit_before>// Copyright 2015 Claudemiro Alves Feitosa Neto. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package gochip8

import (
	"testing"

	"github.com/bmizerany/assert"
)

// dumbSound - Only for testing purpuses
type dumbSound struct {
	BeepCalled bool
}

func (s *dumbSound) Beep() {
	(*s).BeepCalled = true
}

// newCpuAt creates a new cpu and write the ins to the pc memory location
// Only for testing purpuse
func newCpuAt(ins uint16) cpu {
	s := &dumbSound{}
	c := newCpu(s)
	c.memory.WriteWord(uint16(c.pc), ins)

	return c
}

func TestTimers(t *testing.T) {
	s := &dumbSound{}
	c := newCpu(s)

	// With Beep
	c.memory.WriteWord(uint16(c.pc), 0x0E0)

	c.dt = 1
	c.st = 1

	assert.Equal(t, s.BeepCalled, false)

	c.Step()

	assert.Equal(t, c.dt, byte(0))
	assert.Equal(t, c.st, byte(0))
	assert.Equal(t, s.BeepCalled, true)

	// No Beep
	c.memory.WriteWord(uint16(c.pc), 0x0E0)
	s.BeepCalled = false

	c.st = 2
	c.Step()

	assert.Equal(t, s.BeepCalled, false)
	assert.Equal(t, c.st, byte(1))
}

// 00E0 - CLS
func Test00E0(t *testing.T) {

	c := newCpuAt(0x00E0)
	c.gfx.SetPixel(0, 0)
	c.Step()

	for i := 0; i < 64; i++ {
		for j := 0; j < 32; j++ {
			assert.Equal(t, byte(COLOR_BLACK), byte(c.gfx.GetPixel(i, j)))
		}
	}
}

// 00EE - RET
func Test00EE(t *testing.T) {
	c := newCpuAt(0x00EE)

	c.stack.Push(pc(1))
	c.Step()

	assert.Equal(t, pc(1), c.pc)
}

// 1nnn - JP addr
func Test1000(t *testing.T) {
	c := newCpuAt(0x1FFF)
	c.Step()

	assert.Equal(t, pc(0x0FFF), c.pc)
}

// 2nnn - CALL addr
func Test2000(t *testing.T) {
	c := newCpuAt(0x2FFF)
	oldPC := c.pc + 2 // The increment happen before the Step

	c.Step()

	assert.Equal(t, oldPC, c.stack.Pop())
	assert.Equal(t, pc(0x0FFF), c.pc)
}

// 3xkk - SE Vx, byte
func Test3000Equal(t *testing.T) {
	c := newCpuAt(0x31FF)
	c.regs[1] = 0xFF

	oldPC := c.pc + 4
	c.Step()

	assert.Equal(t, oldPC, c.pc)
}

// 3xkk - SE Vx, byte
func Test3000NotEqual(t *testing.T) {
	c := newCpuAt(0x31FF)
	c.regs[1] = 0xAA

	oldPC := c.pc + 2
	c.Step()

	assert.Equal(t, oldPC, c.pc)
}

// 4xkk - SNE Vx, byte
func Test4000Equal(t *testing.T) {
	c := newCpuAt(0x41FF)
	c.regs[1] = 0xFF

	oldPC := c.pc + 2
	c.Step()

	assert.Equal(t, oldPC, c.pc)
}

// 4xkk - SNE Vx, byte
func Test4000NotEqual(t *testing.T) {
	c := newCpuAt(0x41FF)
	c.regs[1] = 0xAA

	oldPC := c.pc + 4
	c.Step()

	assert.Equal(t, oldPC, c.pc)
}

// 5xy0 - SE Vx, Vy
func Test5000Equal(t *testing.T) {
	c := newCpuAt(0x512F)
	c.regs[1] = 0xFF
	c.regs[2] = 0xFF

	oldPC := c.pc + 4
	c.Step()

	assert.Equal(t, oldPC, c.pc)
}

// 5xy0 - SE Vx, Vy
func Test5000NotEqual(t *testing.T) {
	c := newCpuAt(0x512F)
	c.regs[1] = 0xFF
	c.regs[2] = 0xAA

	oldPC := c.pc + 2
	c.Step()

	assert.Equal(t, oldPC, c.pc)
}

// 6xkk - LD Vx, byte
func Test6000(t *testing.T) {
	c := newCpuAt(0x61FF)
	c.Step()
	assert.Equal(t, c.regs[1], byte(0xFF))
}

// 7xkk - ADD Vx, byte
func Test7000(t *testing.T) {
	c := newCpuAt(0x7101)
	c.regs[1] = 1
	c.Step()
	assert.Equal(t, c.regs[1], byte(2))
}

// 8xy0 - LD Vx, Vy
func Test8xy0(t *testing.T) {
	c := newCpuAt(0x8120)
	c.regs[1] = 1
	c.regs[2] = 0
	assert.Equal(t, c.regs[1], byte(1))
	assert.Equal(t, c.regs[2], byte(0))
	c.Step()
	assert.Equal(t, c.regs[1], byte(0))
	assert.Equal(t, c.regs[2], byte(0))
}

// 8xy1 - OR Vx, Vy
func Test8xy1(t *testing.T) {
	c := newCpuAt(0x8121)
	c.regs[1] = 1
	c.regs[2] = 2
	assert.Equal(t, c.regs[1], byte(1))
	assert.Equal(t, c.regs[2], byte(2))
	c.Step()
	assert.Equal(t, c.regs[1], byte(1|2))
	assert.Equal(t, c.regs[2], byte(2))
}

// 8xy2 - OR Vx, Vy
func Test8xy2(t *testing.T) {
	c := newCpuAt(0x8122)
	c.regs[1] = 1
	c.regs[2] = 2
	assert.Equal(t, c.regs[1], byte(1))
	assert.Equal(t, c.regs[2], byte(2))
	c.Step()
	assert.Equal(t, c.regs[1], byte(1&2))
	assert.Equal(t, c.regs[2], byte(2))
}

// 8xy3 - OR Vx, Vy
func Test8xy3(t *testing.T) {
	c := newCpuAt(0x8123)
	c.regs[1] = 1
	c.regs[2] = 2
	assert.Equal(t, c.regs[1], byte(1))
	assert.Equal(t, c.regs[2], byte(2))
	c.Step()
	assert.Equal(t, c.regs[1], byte(1^2))
	assert.Equal(t, c.regs[2], byte(2))
}

// 8xy4 - ADD Vx, Vy
func Test8xy4Overflow(t *testing.T) {
	c := newCpuAt(0x8124)
	c.regs[1] = 0xFF
	c.regs[2] = 1

	assert.Equal(t, c.regs[0xF], byte(0))

	c.Step()

	assert.Equal(t, c.regs[1], byte(0))
	assert.Equal(t, c.regs[0xF], byte(1))
}

// 8xy4 - ADD Vx, Vy
func Test8xy4ONotverflow(t *testing.T) {
	c := newCpuAt(0x8124)
	c.regs[1] = 0xF0
	c.regs[2] = 1

	assert.Equal(t, c.regs[0xF], byte(0))

	c.Step()

	assert.Equal(t, c.regs[1], byte(0xF0+1))
	assert.Equal(t, c.regs[0xF], byte(0))
}

// 8xy5 - SUB Vx, Vy
func Test8xy5Greater(t *testing.T) {
	c := newCpuAt(0x8125)
	c.regs[1] = 2
	c.regs[2] = 1

	assert.Equal(t, c.regs[0xF], byte(0))

	c.Step()

	assert.Equal(t, c.regs[1], byte(1))
	assert.Equal(t, c.regs[0xF], byte(1))
}

// 8xy5 - SUB Vx, Vy
func Test8xy5NotGreater(t *testing.T) {
	c := newCpuAt(0x8125)
	c.regs[1] = 1
	c.regs[2] = 2

	assert.Equal(t, c.regs[0xF], byte(0))

	c.Step()

	assert.Equal(t, c.regs[1], byte(0xFF))
	assert.Equal(t, c.regs[0xF], byte(0))
}

// 8xy6 - SHR Vx {, Vy}
func Test8xy6(t *testing.T) {
	c := newCpuAt(0x8126)
	c.regs[1] = 1

	c.Step()

	assert.Equal(t, c.regs[0xF], byte(1&0x0001))
	assert.Equal(t, c.regs[1], byte(1/2))
}

// 8xy7 - SUBN Vx, Vy
func Test8xy7Greater(t *testing.T) {
	c := newCpuAt(0x8127)
	c.regs[1] = 1
	c.regs[2] = 2

	assert.Equal(t, c.regs[0xF], byte(0))

	c.Step()

	assert.Equal(t, c.regs[1], byte(1))
	assert.Equal(t, c.regs[0xF], byte(1))
}

// 8xy7 - SUBN Vx, Vy
func Test8xy7NotGreater(t *testing.T) {
	c := newCpuAt(0x8127)
	c.regs[1] = 2
	c.regs[2] = 1

	assert.Equal(t, c.regs[0xF], byte(0))

	c.Step()

	assert.Equal(t, c.regs[1], byte(0xFF))
	assert.Equal(t, c.regs[0xF], byte(0))
}
<commit_msg>Added test for 8xyE<commit_after>// Copyright 2015 Claudemiro Alves Feitosa Neto. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package gochip8

import (
	"testing"

	"github.com/bmizerany/assert"
)

// dumbSound - Only for testing purpuses
type dumbSound struct {
	BeepCalled bool
}

func (s *dumbSound) Beep() {
	(*s).BeepCalled = true
}

// newCpuAt creates a new cpu and write the ins to the pc memory location
// Only for testing purpuse
func newCpuAt(ins uint16) cpu {
	s := &dumbSound{}
	c := newCpu(s)
	c.memory.WriteWord(uint16(c.pc), ins)

	return c
}

func TestTimers(t *testing.T) {
	s := &dumbSound{}
	c := newCpu(s)

	// With Beep
	c.memory.WriteWord(uint16(c.pc), 0x0E0)

	c.dt = 1
	c.st = 1

	assert.Equal(t, s.BeepCalled, false)

	c.Step()

	assert.Equal(t, c.dt, byte(0))
	assert.Equal(t, c.st, byte(0))
	assert.Equal(t, s.BeepCalled, true)

	// No Beep
	c.memory.WriteWord(uint16(c.pc), 0x0E0)
	s.BeepCalled = false

	c.st = 2
	c.Step()

	assert.Equal(t, s.BeepCalled, false)
	assert.Equal(t, c.st, byte(1))
}

// 00E0 - CLS
func Test00E0(t *testing.T) {

	c := newCpuAt(0x00E0)
	c.gfx.SetPixel(0, 0)
	c.Step()

	for i := 0; i < 64; i++ {
		for j := 0; j < 32; j++ {
			assert.Equal(t, byte(COLOR_BLACK), byte(c.gfx.GetPixel(i, j)))
		}
	}
}

// 00EE - RET
func Test00EE(t *testing.T) {
	c := newCpuAt(0x00EE)

	c.stack.Push(pc(1))
	c.Step()

	assert.Equal(t, pc(1), c.pc)
}

// 1nnn - JP addr
func Test1000(t *testing.T) {
	c := newCpuAt(0x1FFF)
	c.Step()

	assert.Equal(t, pc(0x0FFF), c.pc)
}

// 2nnn - CALL addr
func Test2000(t *testing.T) {
	c := newCpuAt(0x2FFF)
	oldPC := c.pc + 2 // The increment happen before the Step

	c.Step()

	assert.Equal(t, oldPC, c.stack.Pop())
	assert.Equal(t, pc(0x0FFF), c.pc)
}

// 3xkk - SE Vx, byte
func Test3000Equal(t *testing.T) {
	c := newCpuAt(0x31FF)
	c.regs[1] = 0xFF

	oldPC := c.pc + 4
	c.Step()

	assert.Equal(t, oldPC, c.pc)
}

// 3xkk - SE Vx, byte
func Test3000NotEqual(t *testing.T) {
	c := newCpuAt(0x31FF)
	c.regs[1] = 0xAA

	oldPC := c.pc + 2
	c.Step()

	assert.Equal(t, oldPC, c.pc)
}

// 4xkk - SNE Vx, byte
func Test4000Equal(t *testing.T) {
	c := newCpuAt(0x41FF)
	c.regs[1] = 0xFF

	oldPC := c.pc + 2
	c.Step()

	assert.Equal(t, oldPC, c.pc)
}

// 4xkk - SNE Vx, byte
func Test4000NotEqual(t *testing.T) {
	c := newCpuAt(0x41FF)
	c.regs[1] = 0xAA

	oldPC := c.pc + 4
	c.Step()

	assert.Equal(t, oldPC, c.pc)
}

// 5xy0 - SE Vx, Vy
func Test5000Equal(t *testing.T) {
	c := newCpuAt(0x512F)
	c.regs[1] = 0xFF
	c.regs[2] = 0xFF

	oldPC := c.pc + 4
	c.Step()

	assert.Equal(t, oldPC, c.pc)
}

// 5xy0 - SE Vx, Vy
func Test5000NotEqual(t *testing.T) {
	c := newCpuAt(0x512F)
	c.regs[1] = 0xFF
	c.regs[2] = 0xAA

	oldPC := c.pc + 2
	c.Step()

	assert.Equal(t, oldPC, c.pc)
}

// 6xkk - LD Vx, byte
func Test6000(t *testing.T) {
	c := newCpuAt(0x61FF)
	c.Step()
	assert.Equal(t, c.regs[1], byte(0xFF))
}

// 7xkk - ADD Vx, byte
func Test7000(t *testing.T) {
	c := newCpuAt(0x7101)
	c.regs[1] = 1
	c.Step()
	assert.Equal(t, c.regs[1], byte(2))
}

// 8xy0 - LD Vx, Vy
func Test8xy0(t *testing.T) {
	c := newCpuAt(0x8120)
	c.regs[1] = 1
	c.regs[2] = 0
	assert.Equal(t, c.regs[1], byte(1))
	assert.Equal(t, c.regs[2], byte(0))
	c.Step()
	assert.Equal(t, c.regs[1], byte(0))
	assert.Equal(t, c.regs[2], byte(0))
}

// 8xy1 - OR Vx, Vy
func Test8xy1(t *testing.T) {
	c := newCpuAt(0x8121)
	c.regs[1] = 1
	c.regs[2] = 2
	assert.Equal(t, c.regs[1], byte(1))
	assert.Equal(t, c.regs[2], byte(2))
	c.Step()
	assert.Equal(t, c.regs[1], byte(1|2))
	assert.Equal(t, c.regs[2], byte(2))
}

// 8xy2 - OR Vx, Vy
func Test8xy2(t *testing.T) {
	c := newCpuAt(0x8122)
	c.regs[1] = 1
	c.regs[2] = 2
	assert.Equal(t, c.regs[1], byte(1))
	assert.Equal(t, c.regs[2], byte(2))
	c.Step()
	assert.Equal(t, c.regs[1], byte(1&2))
	assert.Equal(t, c.regs[2], byte(2))
}

// 8xy3 - OR Vx, Vy
func Test8xy3(t *testing.T) {
	c := newCpuAt(0x8123)
	c.regs[1] = 1
	c.regs[2] = 2
	assert.Equal(t, c.regs[1], byte(1))
	assert.Equal(t, c.regs[2], byte(2))
	c.Step()
	assert.Equal(t, c.regs[1], byte(1^2))
	assert.Equal(t, c.regs[2], byte(2))
}

// 8xy4 - ADD Vx, Vy
func Test8xy4Overflow(t *testing.T) {
	c := newCpuAt(0x8124)
	c.regs[1] = 0xFF
	c.regs[2] = 1

	assert.Equal(t, c.regs[0xF], byte(0))

	c.Step()

	assert.Equal(t, c.regs[1], byte(0))
	assert.Equal(t, c.regs[0xF], byte(1))
}

// 8xy4 - ADD Vx, Vy
func Test8xy4ONotverflow(t *testing.T) {
	c := newCpuAt(0x8124)
	c.regs[1] = 0xF0
	c.regs[2] = 1

	assert.Equal(t, c.regs[0xF], byte(0))

	c.Step()

	assert.Equal(t, c.regs[1], byte(0xF0+1))
	assert.Equal(t, c.regs[0xF], byte(0))
}

// 8xy5 - SUB Vx, Vy
func Test8xy5Greater(t *testing.T) {
	c := newCpuAt(0x8125)
	c.regs[1] = 2
	c.regs[2] = 1

	assert.Equal(t, c.regs[0xF], byte(0))

	c.Step()

	assert.Equal(t, c.regs[1], byte(1))
	assert.Equal(t, c.regs[0xF], byte(1))
}

// 8xy5 - SUB Vx, Vy
func Test8xy5NotGreater(t *testing.T) {
	c := newCpuAt(0x8125)
	c.regs[1] = 1
	c.regs[2] = 2

	assert.Equal(t, c.regs[0xF], byte(0))

	c.Step()

	assert.Equal(t, c.regs[1], byte(0xFF))
	assert.Equal(t, c.regs[0xF], byte(0))
}

// 8xy6 - SHR Vx {, Vy}
func Test8xy6(t *testing.T) {
	c := newCpuAt(0x8126)
	c.regs[1] = 1

	c.Step()

	assert.Equal(t, c.regs[0xF], byte(1&0x0001))
	assert.Equal(t, c.regs[1], byte(1/2))
}

// 8xy7 - SUBN Vx, Vy
func Test8xy7Greater(t *testing.T) {
	c := newCpuAt(0x8127)
	c.regs[1] = 1
	c.regs[2] = 2

	assert.Equal(t, c.regs[0xF], byte(0))

	c.Step()

	assert.Equal(t, c.regs[1], byte(1))
	assert.Equal(t, c.regs[0xF], byte(1))
}

// 8xy7 - SUBN Vx, Vy
func Test8xy7NotGreater(t *testing.T) {
	c := newCpuAt(0x8127)
	c.regs[1] = 2
	c.regs[2] = 1

	assert.Equal(t, c.regs[0xF], byte(0))

	c.Step()

	assert.Equal(t, c.regs[1], byte(0xFF))
	assert.Equal(t, c.regs[0xF], byte(0))
}

// 8xyE - SHL Vx {, Vy}
func Test8xyE(t *testing.T) {
	c := newCpuAt(0x812E)
	c.regs[1] = 1

	c.Step()

	assert.Equal(t, c.regs[0xF], byte(1&0x0001))
	assert.Equal(t, c.regs[1], byte(1*2))
}
<|endoftext|>


<commit_before>package cobra

import (
	"bytes"
	"fmt"
	"io"
	"os"
)

func (c *Command) genBashCompletion(w io.Writer, includeDesc bool) error {
	buf := new(bytes.Buffer)
	genBashComp(buf, c.Name(), includeDesc)
	_, err := buf.WriteTo(w)
	return err
}

func genBashComp(buf io.StringWriter, name string, includeDesc bool) {
	compCmd := ShellCompRequestCmd
	if !includeDesc {
		compCmd = ShellCompNoDescRequestCmd
	}

	WriteStringAndCheck(buf, fmt.Sprintf(`# bash completion V2 for %-36[1]s -*- shell-script -*-

__%[1]s_debug()
{
    if [[ -n ${BASH_COMP_DEBUG_FILE:-} ]]; then
        echo "$*" >> "${BASH_COMP_DEBUG_FILE}"
    fi
}

# Macs have bash3 for which the bash-completion package doesn't include
# _init_completion. This is a minimal version of that function.
__%[1]s_init_completion()
{
    COMPREPLY=()
    _get_comp_words_by_ref "$@" cur prev words cword
}

# This function calls the %[1]s program to obtain the completion
# results and the directive.  It fills the 'out' and 'directive' vars.
__%[1]s_get_completion_results() {
    local requestComp lastParam lastChar args

    # Prepare the command to request completions for the program.
    # Calling ${words[0]} instead of directly %[1]s allows to handle aliases
    args=("${words[@]:1}")
    requestComp="${words[0]} %[2]s ${args[*]}"

    lastParam=${words[$((${#words[@]}-1))]}
    lastChar=${lastParam:$((${#lastParam}-1)):1}
    __%[1]s_debug "lastParam ${lastParam}, lastChar ${lastChar}"

    if [ -z "${cur}" ] && [ "${lastChar}" != "=" ]; then
        # If the last parameter is complete (there is a space following it)
        # We add an extra empty parameter so we can indicate this to the go method.
        __%[1]s_debug "Adding extra empty parameter"
        requestComp="${requestComp} ''"
    fi

    # When completing a flag with an = (e.g., %[1]s -n=<TAB>)
    # bash focuses on the part after the =, so we need to remove
    # the flag part from $cur
    if [[ "${cur}" == -*=* ]]; then
        cur="${cur#*=}"
    fi

    __%[1]s_debug "Calling ${requestComp}"
    # Use eval to handle any environment variables and such
    out=$(eval "${requestComp}" 2>/dev/null)

    # Extract the directive integer at the very end of the output following a colon (:)
    directive=${out##*:}
    # Remove the directive
    out=${out%%:*}
    if [ "${directive}" = "${out}" ]; then
        # There is not directive specified
        directive=0
    fi
    __%[1]s_debug "The completion directive is: ${directive}"
    __%[1]s_debug "The completions are: ${out}"
}

__%[1]s_process_completion_results() {
    local shellCompDirectiveError=%[3]d
    local shellCompDirectiveNoSpace=%[4]d
    local shellCompDirectiveNoFileComp=%[5]d
    local shellCompDirectiveFilterFileExt=%[6]d
    local shellCompDirectiveFilterDirs=%[7]d

    if [ $((directive & shellCompDirectiveError)) -ne 0 ]; then
        # Error code.  No completion.
        __%[1]s_debug "Received error from custom completion go code"
        return
    else
        if [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ]; then
            if [[ $(type -t compopt) = "builtin" ]]; then
                __%[1]s_debug "Activating no space"
                compopt -o nospace
            else
                __%[1]s_debug "No space directive not supported in this version of bash"
            fi
        fi
        if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then
            if [[ $(type -t compopt) = "builtin" ]]; then
                __%[1]s_debug "Activating no file completion"
                compopt +o default
            else
                __%[1]s_debug "No file completion directive not supported in this version of bash"
            fi
        fi
    fi

    # Separate activeHelp from normal completions
    local completions=()
    local activeHelp=()
    __%[1]s_extract_activeHelp

    if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then
        # File extension filtering
        local fullFilter filter filteringCmd

        # Do not use quotes around the $completions variable or else newline
        # characters will be kept.
        for filter in ${completions[*]}; do
            fullFilter+="$filter|"
        done

        filteringCmd="_filedir $fullFilter"
        __%[1]s_debug "File filtering command: $filteringCmd"
        $filteringCmd
    elif [ $((directive & shellCompDirectiveFilterDirs)) -ne 0 ]; then
        # File completion for directories only

        # Use printf to strip any trailing newline
        local subdir
        subdir=$(printf "%%s" "${completions[0]}")
        if [ -n "$subdir" ]; then
            __%[1]s_debug "Listing directories in $subdir"
            pushd "$subdir" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 || return
        else
            __%[1]s_debug "Listing directories in ."
            _filedir -d
        fi
    else
        __%[1]s_handle_completion_types
    fi

    __%[1]s_handle_special_char "$cur" :
    __%[1]s_handle_special_char "$cur" =

    # Print the activeHelp statements before we finish
    if [ ${#activeHelp} -ne 0 ]; then
        printf "\n";
        printf "%%s\n" "${activeHelp[@]}"
        printf "\n"

        # The prompt format is only available from bash 4.4.
        # We test if it is available before using it.
        if (x=${PS1@P}) 2> /dev/null; then
            printf "%%s" "${PS1@P}${COMP_LINE[@]}"
        else
            # Can't print the prompt.  Just print the
            # text the user had typed, it is workable enough.
            printf "%%s" "${COMP_LINE[@]}"
        fi
    fi
}

# Separate activeHelp lines from real completions.
# Fills the $activeHelp and $completions arrays.
__%[1]s_extract_activeHelp() {
    local activeHelpMarker="%[8]s"
    local endIndex=${#activeHelpMarker}

    while IFS='' read -r comp; do
        if [ "${comp:0:endIndex}" = "$activeHelpMarker" ]; then
            comp=${comp:endIndex}
            __%[1]s_debug "ActiveHelp found: $comp"
            if [ -n "$comp" ]; then
                activeHelp+=("$comp")
            fi
        else
            # Not an activeHelp line but a normal completion
            completions+=("$comp")
        fi
    done < <(printf "%%s\n" "${out}")
}

__%[1]s_handle_completion_types() {
    __%[1]s_debug "__%[1]s_handle_completion_types: COMP_TYPE is $COMP_TYPE"

    case $COMP_TYPE in
    37|42)
        # Type: menu-complete/menu-complete-backward and insert-completions
        # If the user requested inserting one completion at a time, or all
        # completions at once on the command-line we must remove the descriptions.
        # https://github.com/spf13/cobra/issues/1508
        local tab=$'\t' comp
        while IFS='' read -r comp; do
            [[ -z $comp ]] && continue
            # Strip any description
            comp=${comp%%%%$tab*}
            # Only consider the completions that match
            if [[ $comp == "$cur"* ]]; then
                COMPREPLY+=("$comp")
            fi
        done < <(printf "%%s\n" "${completions[@]}")
        ;;

    *)
        # Type: complete (normal completion)
        __%[1]s_handle_standard_completion_case
        ;;
    esac
}

__%[1]s_handle_standard_completion_case() {
    local tab=$'\t' comp

    # Short circuit to optimize if we don't have descriptions
    if [[ "${completions[*]}" != *$tab* ]]; then
        IFS=$'\n' read -ra COMPREPLY -d '' < <(compgen -W "${completions[*]}" -- "$cur")
        return 0
    fi

    local longest=0
    local compline
    # Look for the longest completion so that we can format things nicely
    while IFS='' read -r compline; do
        [[ -z $compline ]] && continue
        # Strip any description before checking the length
        comp=${compline%%%%$tab*}
        # Only consider the completions that match
        [[ $comp == "$cur"* ]] || continue
        COMPREPLY+=("$compline")
        if ((${#comp}>longest)); then
            longest=${#comp}
        fi
    done < <(printf "%%s\n" "${completions[@]}")

    # If there is a single completion left, remove the description text
    if [ ${#COMPREPLY[*]} -eq 1 ]; then
        __%[1]s_debug "COMPREPLY[0]: ${COMPREPLY[0]}"
        comp="${COMPREPLY[0]%%%%$tab*}"
        __%[1]s_debug "Removed description from single completion, which is now: ${comp}"
        COMPREPLY[0]=$comp
    else # Format the descriptions
        __%[1]s_format_comp_descriptions $longest
    fi
}

__%[1]s_handle_special_char()
{
    local comp="$1"
    local char=$2
    if [[ "$comp" == *${char}* && "$COMP_WORDBREAKS" == *${char}* ]]; then
        local word=${comp%%"${comp##*${char}}"}
        local idx=${#COMPREPLY[*]}
        while [[ $((--idx)) -ge 0 ]]; do
            COMPREPLY[$idx]=${COMPREPLY[$idx]#"$word"}
        done
    fi
}

__%[1]s_format_comp_descriptions()
{
    local tab=$'\t'
    local comp desc maxdesclength
    local longest=$1

    local i ci
    for ci in ${!COMPREPLY[*]}; do
        comp=${COMPREPLY[ci]}
        # Properly format the description string which follows a tab character if there is one
        if [[ "$comp" == *$tab* ]]; then
            __%[1]s_debug "Original comp: $comp"
            desc=${comp#*$tab}
            comp=${comp%%%%$tab*}

            # $COLUMNS stores the current shell width.
            # Remove an extra 4 because we add 2 spaces and 2 parentheses.
            maxdesclength=$(( COLUMNS - longest - 4 ))

            # Make sure we can fit a description of at least 8 characters
            # if we are to align the descriptions.
            if [[ $maxdesclength -gt 8 ]]; then
                # Add the proper number of spaces to align the descriptions
                for ((i = ${#comp} ; i < longest ; i++)); do
                    comp+=" "
                done
            else
                # Don't pad the descriptions so we can fit more text after the completion
                maxdesclength=$(( COLUMNS - ${#comp} - 4 ))
            fi

            # If there is enough space for any description text,
            # truncate the descriptions that are too long for the shell width
            if [ $maxdesclength -gt 0 ]; then
                if [ ${#desc} -gt $maxdesclength ]; then
                    desc=${desc:0:$(( maxdesclength - 1 ))}
                    desc+="…"
                fi
                comp+="  ($desc)"
            fi
            COMPREPLY[ci]=$comp
            __%[1]s_debug "Final comp: $comp"
        fi
    done
}

__start_%[1]s()
{
    local cur prev words cword split

    COMPREPLY=()

    # Call _init_completion from the bash-completion package
    # to prepare the arguments properly
    if declare -F _init_completion >/dev/null 2>&1; then
        _init_completion -n "=:" || return
    else
        __%[1]s_init_completion -n "=:" || return
    fi

    __%[1]s_debug
    __%[1]s_debug "========= starting completion logic =========="
    __%[1]s_debug "cur is ${cur}, words[*] is ${words[*]}, #words[@] is ${#words[@]}, cword is $cword"

    # The user could have moved the cursor backwards on the command-line.
    # We need to trigger completion from the $cword location, so we need
    # to truncate the command-line ($words) up to the $cword location.
    words=("${words[@]:0:$cword+1}")
    __%[1]s_debug "Truncated words[*]: ${words[*]},"

    local out directive
    __%[1]s_get_completion_results
    __%[1]s_process_completion_results
}

if [[ $(type -t compopt) = "builtin" ]]; then
    complete -o default -F __start_%[1]s %[1]s
else
    complete -o default -o nospace -F __start_%[1]s %[1]s
fi

# ex: ts=4 sw=4 et filetype=sh
`, name, compCmd,
		ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
		ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs,
		activeHelpMarker))
}

// GenBashCompletionFileV2 generates Bash completion version 2.
func (c *Command) GenBashCompletionFileV2(filename string, includeDesc bool) error {
	outFile, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer outFile.Close()

	return c.GenBashCompletionV2(outFile, includeDesc)
}

// GenBashCompletionV2 generates Bash completion file version 2
// and writes it to the passed writer.
func (c *Command) GenBashCompletionV2(w io.Writer, includeDesc bool) error {
	return c.genBashCompletion(w, includeDesc)
}
<commit_msg>fix(bash-v2): activeHelp length check syntax (#1762)<commit_after>package cobra

import (
	"bytes"
	"fmt"
	"io"
	"os"
)

func (c *Command) genBashCompletion(w io.Writer, includeDesc bool) error {
	buf := new(bytes.Buffer)
	genBashComp(buf, c.Name(), includeDesc)
	_, err := buf.WriteTo(w)
	return err
}

func genBashComp(buf io.StringWriter, name string, includeDesc bool) {
	compCmd := ShellCompRequestCmd
	if !includeDesc {
		compCmd = ShellCompNoDescRequestCmd
	}

	WriteStringAndCheck(buf, fmt.Sprintf(`# bash completion V2 for %-36[1]s -*- shell-script -*-

__%[1]s_debug()
{
    if [[ -n ${BASH_COMP_DEBUG_FILE:-} ]]; then
        echo "$*" >> "${BASH_COMP_DEBUG_FILE}"
    fi
}

# Macs have bash3 for which the bash-completion package doesn't include
# _init_completion. This is a minimal version of that function.
__%[1]s_init_completion()
{
    COMPREPLY=()
    _get_comp_words_by_ref "$@" cur prev words cword
}

# This function calls the %[1]s program to obtain the completion
# results and the directive.  It fills the 'out' and 'directive' vars.
__%[1]s_get_completion_results() {
    local requestComp lastParam lastChar args

    # Prepare the command to request completions for the program.
    # Calling ${words[0]} instead of directly %[1]s allows to handle aliases
    args=("${words[@]:1}")
    requestComp="${words[0]} %[2]s ${args[*]}"

    lastParam=${words[$((${#words[@]}-1))]}
    lastChar=${lastParam:$((${#lastParam}-1)):1}
    __%[1]s_debug "lastParam ${lastParam}, lastChar ${lastChar}"

    if [ -z "${cur}" ] && [ "${lastChar}" != "=" ]; then
        # If the last parameter is complete (there is a space following it)
        # We add an extra empty parameter so we can indicate this to the go method.
        __%[1]s_debug "Adding extra empty parameter"
        requestComp="${requestComp} ''"
    fi

    # When completing a flag with an = (e.g., %[1]s -n=<TAB>)
    # bash focuses on the part after the =, so we need to remove
    # the flag part from $cur
    if [[ "${cur}" == -*=* ]]; then
        cur="${cur#*=}"
    fi

    __%[1]s_debug "Calling ${requestComp}"
    # Use eval to handle any environment variables and such
    out=$(eval "${requestComp}" 2>/dev/null)

    # Extract the directive integer at the very end of the output following a colon (:)
    directive=${out##*:}
    # Remove the directive
    out=${out%%:*}
    if [ "${directive}" = "${out}" ]; then
        # There is not directive specified
        directive=0
    fi
    __%[1]s_debug "The completion directive is: ${directive}"
    __%[1]s_debug "The completions are: ${out}"
}

__%[1]s_process_completion_results() {
    local shellCompDirectiveError=%[3]d
    local shellCompDirectiveNoSpace=%[4]d
    local shellCompDirectiveNoFileComp=%[5]d
    local shellCompDirectiveFilterFileExt=%[6]d
    local shellCompDirectiveFilterDirs=%[7]d

    if [ $((directive & shellCompDirectiveError)) -ne 0 ]; then
        # Error code.  No completion.
        __%[1]s_debug "Received error from custom completion go code"
        return
    else
        if [ $((directive & shellCompDirectiveNoSpace)) -ne 0 ]; then
            if [[ $(type -t compopt) = "builtin" ]]; then
                __%[1]s_debug "Activating no space"
                compopt -o nospace
            else
                __%[1]s_debug "No space directive not supported in this version of bash"
            fi
        fi
        if [ $((directive & shellCompDirectiveNoFileComp)) -ne 0 ]; then
            if [[ $(type -t compopt) = "builtin" ]]; then
                __%[1]s_debug "Activating no file completion"
                compopt +o default
            else
                __%[1]s_debug "No file completion directive not supported in this version of bash"
            fi
        fi
    fi

    # Separate activeHelp from normal completions
    local completions=()
    local activeHelp=()
    __%[1]s_extract_activeHelp

    if [ $((directive & shellCompDirectiveFilterFileExt)) -ne 0 ]; then
        # File extension filtering
        local fullFilter filter filteringCmd

        # Do not use quotes around the $completions variable or else newline
        # characters will be kept.
        for filter in ${completions[*]}; do
            fullFilter+="$filter|"
        done

        filteringCmd="_filedir $fullFilter"
        __%[1]s_debug "File filtering command: $filteringCmd"
        $filteringCmd
    elif [ $((directive & shellCompDirectiveFilterDirs)) -ne 0 ]; then
        # File completion for directories only

        # Use printf to strip any trailing newline
        local subdir
        subdir=$(printf "%%s" "${completions[0]}")
        if [ -n "$subdir" ]; then
            __%[1]s_debug "Listing directories in $subdir"
            pushd "$subdir" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 || return
        else
            __%[1]s_debug "Listing directories in ."
            _filedir -d
        fi
    else
        __%[1]s_handle_completion_types
    fi

    __%[1]s_handle_special_char "$cur" :
    __%[1]s_handle_special_char "$cur" =

    # Print the activeHelp statements before we finish
    if [ ${#activeHelp[*]} -ne 0 ]; then
        printf "\n";
        printf "%%s\n" "${activeHelp[@]}"
        printf "\n"

        # The prompt format is only available from bash 4.4.
        # We test if it is available before using it.
        if (x=${PS1@P}) 2> /dev/null; then
            printf "%%s" "${PS1@P}${COMP_LINE[@]}"
        else
            # Can't print the prompt.  Just print the
            # text the user had typed, it is workable enough.
            printf "%%s" "${COMP_LINE[@]}"
        fi
    fi
}

# Separate activeHelp lines from real completions.
# Fills the $activeHelp and $completions arrays.
__%[1]s_extract_activeHelp() {
    local activeHelpMarker="%[8]s"
    local endIndex=${#activeHelpMarker}

    while IFS='' read -r comp; do
        if [ "${comp:0:endIndex}" = "$activeHelpMarker" ]; then
            comp=${comp:endIndex}
            __%[1]s_debug "ActiveHelp found: $comp"
            if [ -n "$comp" ]; then
                activeHelp+=("$comp")
            fi
        else
            # Not an activeHelp line but a normal completion
            completions+=("$comp")
        fi
    done < <(printf "%%s\n" "${out}")
}

__%[1]s_handle_completion_types() {
    __%[1]s_debug "__%[1]s_handle_completion_types: COMP_TYPE is $COMP_TYPE"

    case $COMP_TYPE in
    37|42)
        # Type: menu-complete/menu-complete-backward and insert-completions
        # If the user requested inserting one completion at a time, or all
        # completions at once on the command-line we must remove the descriptions.
        # https://github.com/spf13/cobra/issues/1508
        local tab=$'\t' comp
        while IFS='' read -r comp; do
            [[ -z $comp ]] && continue
            # Strip any description
            comp=${comp%%%%$tab*}
            # Only consider the completions that match
            if [[ $comp == "$cur"* ]]; then
                COMPREPLY+=("$comp")
            fi
        done < <(printf "%%s\n" "${completions[@]}")
        ;;

    *)
        # Type: complete (normal completion)
        __%[1]s_handle_standard_completion_case
        ;;
    esac
}

__%[1]s_handle_standard_completion_case() {
    local tab=$'\t' comp

    # Short circuit to optimize if we don't have descriptions
    if [[ "${completions[*]}" != *$tab* ]]; then
        IFS=$'\n' read -ra COMPREPLY -d '' < <(compgen -W "${completions[*]}" -- "$cur")
        return 0
    fi

    local longest=0
    local compline
    # Look for the longest completion so that we can format things nicely
    while IFS='' read -r compline; do
        [[ -z $compline ]] && continue
        # Strip any description before checking the length
        comp=${compline%%%%$tab*}
        # Only consider the completions that match
        [[ $comp == "$cur"* ]] || continue
        COMPREPLY+=("$compline")
        if ((${#comp}>longest)); then
            longest=${#comp}
        fi
    done < <(printf "%%s\n" "${completions[@]}")

    # If there is a single completion left, remove the description text
    if [ ${#COMPREPLY[*]} -eq 1 ]; then
        __%[1]s_debug "COMPREPLY[0]: ${COMPREPLY[0]}"
        comp="${COMPREPLY[0]%%%%$tab*}"
        __%[1]s_debug "Removed description from single completion, which is now: ${comp}"
        COMPREPLY[0]=$comp
    else # Format the descriptions
        __%[1]s_format_comp_descriptions $longest
    fi
}

__%[1]s_handle_special_char()
{
    local comp="$1"
    local char=$2
    if [[ "$comp" == *${char}* && "$COMP_WORDBREAKS" == *${char}* ]]; then
        local word=${comp%%"${comp##*${char}}"}
        local idx=${#COMPREPLY[*]}
        while [[ $((--idx)) -ge 0 ]]; do
            COMPREPLY[$idx]=${COMPREPLY[$idx]#"$word"}
        done
    fi
}

__%[1]s_format_comp_descriptions()
{
    local tab=$'\t'
    local comp desc maxdesclength
    local longest=$1

    local i ci
    for ci in ${!COMPREPLY[*]}; do
        comp=${COMPREPLY[ci]}
        # Properly format the description string which follows a tab character if there is one
        if [[ "$comp" == *$tab* ]]; then
            __%[1]s_debug "Original comp: $comp"
            desc=${comp#*$tab}
            comp=${comp%%%%$tab*}

            # $COLUMNS stores the current shell width.
            # Remove an extra 4 because we add 2 spaces and 2 parentheses.
            maxdesclength=$(( COLUMNS - longest - 4 ))

            # Make sure we can fit a description of at least 8 characters
            # if we are to align the descriptions.
            if [[ $maxdesclength -gt 8 ]]; then
                # Add the proper number of spaces to align the descriptions
                for ((i = ${#comp} ; i < longest ; i++)); do
                    comp+=" "
                done
            else
                # Don't pad the descriptions so we can fit more text after the completion
                maxdesclength=$(( COLUMNS - ${#comp} - 4 ))
            fi

            # If there is enough space for any description text,
            # truncate the descriptions that are too long for the shell width
            if [ $maxdesclength -gt 0 ]; then
                if [ ${#desc} -gt $maxdesclength ]; then
                    desc=${desc:0:$(( maxdesclength - 1 ))}
                    desc+="…"
                fi
                comp+="  ($desc)"
            fi
            COMPREPLY[ci]=$comp
            __%[1]s_debug "Final comp: $comp"
        fi
    done
}

__start_%[1]s()
{
    local cur prev words cword split

    COMPREPLY=()

    # Call _init_completion from the bash-completion package
    # to prepare the arguments properly
    if declare -F _init_completion >/dev/null 2>&1; then
        _init_completion -n "=:" || return
    else
        __%[1]s_init_completion -n "=:" || return
    fi

    __%[1]s_debug
    __%[1]s_debug "========= starting completion logic =========="
    __%[1]s_debug "cur is ${cur}, words[*] is ${words[*]}, #words[@] is ${#words[@]}, cword is $cword"

    # The user could have moved the cursor backwards on the command-line.
    # We need to trigger completion from the $cword location, so we need
    # to truncate the command-line ($words) up to the $cword location.
    words=("${words[@]:0:$cword+1}")
    __%[1]s_debug "Truncated words[*]: ${words[*]},"

    local out directive
    __%[1]s_get_completion_results
    __%[1]s_process_completion_results
}

if [[ $(type -t compopt) = "builtin" ]]; then
    complete -o default -F __start_%[1]s %[1]s
else
    complete -o default -o nospace -F __start_%[1]s %[1]s
fi

# ex: ts=4 sw=4 et filetype=sh
`, name, compCmd,
		ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp,
		ShellCompDirectiveFilterFileExt, ShellCompDirectiveFilterDirs,
		activeHelpMarker))
}

// GenBashCompletionFileV2 generates Bash completion version 2.
func (c *Command) GenBashCompletionFileV2(filename string, includeDesc bool) error {
	outFile, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer outFile.Close()

	return c.GenBashCompletionV2(outFile, includeDesc)
}

// GenBashCompletionV2 generates Bash completion file version 2
// and writes it to the passed writer.
func (c *Command) GenBashCompletionV2(w io.Writer, includeDesc bool) error {
	return c.genBashCompletion(w, includeDesc)
}
<|endoftext|>