<commit_before>package main

import "math"
import "fmt"
import "image"
import "os"
import "image/color"
import "image/png"

// vector can represent a point as well, if interpreted as
//  a vector from the origin to a point or 'absolute position vector'.
//  otherwise it represents a 'relative position vector'
type vector struct {
	x, y, z float64
}

type ray struct {
	start vector
	direction vector
}

type camera struct {
	eye vector
	look_at vector
	up vector
}

type screen struct {
	w,h float64
	xres, yres int
}

type sphere struct {
	center vector
	radius,reflectiveness float64
	red,green,blue float64
}

type scene struct {
	items []sceneItem
}

type zplane struct {
	loc, reflectiveness float64
	red,green,blue float64
}

type sceneItem interface {
	intersected(c_ray *ray) (float64, bool)   // returns the t for the intersection, if it occured
	getReflectiveness() (float64)
	getColorRaw() (float64, float64, float64)
	getUnitNormal(point *vector) (*vector)
}

func (z *zplane) getReflectiveness() (float64) {
	return z.reflectiveness
}

func (s *sphere) getReflectiveness() (float64) {
	return s.reflectiveness
}

func (z *zplane) getColorRaw() (float64, float64, float64) {
	return z.red, z.green, z.blue
}

func (s *sphere) getColorRaw() (float64, float64, float64) {
	return s.red, s.green, s.blue
}

func (z *zplane) getUnitNormal(point *vector) (*vector) {
	return &vector{0.0, 0.0, -1.0}
}

func (s *sphere) getUnitNormal(point *vector) (*vector) {
	normal := point.sub(&s.center)
	unormal := normal.unit()
	return &unormal
}

func (the_scene *scene) getColor(c_ray *ray, light *vector, ambient float64) (float64, float64, float64) {
	t_closest := 0.0
	var closest_item sceneItem = nil
	for _, value := range the_scene.items {
		t, is_hit := value.intersected(c_ray)
		if is_hit == false {
			continue
		}
		if closest_item == nil || (t > 0 && t < t_closest) {
			t_closest = t
			closest_item = value
		}
	}

	if closest_item == nil {
		return 0,0,0
	}

	dir := c_ray.direction.scalarMult(t_closest)
	point_on_object:= c_ray.start.add(&dir)

	unormal := closest_item.getUnitNormal(&point_on_object)

	// check for light obstructions
	point_on_object_to_light := light.sub(&point_on_object)
	upoint_on_object_to_light := point_on_object_to_light.unit()

	is_hit:=false
	scale:=0.0
	for _, value := range the_scene.items {
		_, is_hit = value.intersected(&ray{point_on_object, upoint_on_object_to_light})
		if is_hit {
			break
		}
	}

	//calculate the light contribution
	upoint_on_object_to_source := c_ray.direction.scalarMult(-1.0)
	intermediate := unormal.scalarMult(2.0 * upoint_on_object_to_source.dot(unormal))
	reflected := intermediate.sub(&upoint_on_object_to_source)
	ureflected := reflected.unit()

	if is_hit == false {
		scale = ureflected.dot(&upoint_on_object_to_light)
		if scale < 0.0 {
			scale = 0.0
		}
	}

	red,green,blue:=closest_item.getColorRaw()

	red_light := scale*red
	green_light := scale*green
	blue_light := scale*blue

	obj_red:=ceiling(red_light + ambient*red,1.0)
	obj_green:=ceiling(green_light + ambient*green,1.0)
	obj_blue:=ceiling(blue_light + ambient*blue,1.0)

	// send the reflectived ray into the scene
	reflected_red,reflected_green,reflected_blue:=the_scene.getColor(&ray{point_on_object, ureflected},light,ambient)

	reflectiveness := closest_item.getReflectiveness()

	return reflectiveness*reflected_red + (1.0-reflectiveness)*obj_red,
	reflectiveness*reflected_green + (1.0-reflectiveness)*obj_green,
	reflectiveness*reflected_blue + (1.0-reflectiveness)*obj_blue
}

func (z *zplane) intersected(c_ray *ray) (float64, bool)  {
	if c_ray.direction.z == 0.0 {
		return 0.0, false
	}

	t := (z.loc - c_ray.start.z) / c_ray.direction.z
	t = in_buffer(t)
	if t <= 0.0 {
		return 0.0, false
	}

	return t, true
}

var buffer_val float64 = .00001
func in_buffer(val float64) float64{
	if val < buffer_val {
		val = 0.0
	}
	return val
}

func (s *sphere) intersected(c_ray *ray) (float64, bool)  {
	a := c_ray.direction.x * c_ray.direction.x +
		c_ray.direction.y * c_ray.direction.y +
		c_ray.direction.z * c_ray.direction.z
	b := 2.0*((c_ray.start.x-s.center.x)*c_ray.direction.x +
		(c_ray.start.y-s.center.y)*c_ray.direction.y +
		(c_ray.start.z-s.center.z)*c_ray.direction.z)
	c := (c_ray.start.x-s.center.x) * (c_ray.start.x-s.center.x) +
		(c_ray.start.y-s.center.y) * (c_ray.start.y-s.center.y) +
		(c_ray.start.z-s.center.z) * (c_ray.start.z-s.center.z) -
		s.radius * s.radius

	is_hit:=false
	i_test:=b*b-4.0*a*c
	t1,t2,t_closest:=0.0,0.0,0.0
	if i_test >= 0.0 {
		is_hit=true
		t1=(-b+math.Sqrt(i_test))/(2.0*a)
		t2=(-b-math.Sqrt(i_test))/(2.0*a)
		t1=in_buffer(t1)
		t2=in_buffer(t2)
		if t1 <= 0.0 && t2 <= 0.0 {
			is_hit=false  // it hit behind or on the viewer
		}else if t1 > 0.0 && t2 > 0.0 {
			if t1<t2 {
				t_closest=t1
			}else{
				t_closest=t2
			}
		} else if t1 > 0.0 {
			t_closest = t1
		} else if t2 > 0.0 {
			t_closest = t2
		}
	}

	return t_closest, is_hit
}

func (v *vector) sub(v1 *vector) vector {
	return vector{v.x-v1.x, v.y-v1.y, v.z-v1.z}
}

func (v *vector) add(v1 *vector) vector {
	return vector{v.x+v1.x, v.y+v1.y, v.z+v1.z}
}

func (v *vector) scalarMult (c float64) vector {
	return vector{c * v.x, c * v.y, c * v.z}
}

func (v *vector) lengthSq() float64 {
	return v.x * v.x  + v.y * v.y + v.z * v.z
}

func (v *vector) length() float64 {
	return math.Sqrt(v.lengthSq())
}

func (v *vector) unit() vector {
	l := v.length()
	return vector{v.x/l, v.y/l, v.z/l}
}

func (v *vector) dot(v1 *vector) float64 {
	return v.x * v1.x + v.y * v1.y + v.z * v1.z
}

func (v1 *vector) cross(v2 *vector) vector {
	return vector{v1.y * v2.z - v2.y * v1.z,
		v2.x * v1.z - v1.x * v2.z,
		v1.x * v2.y - v2.x * v1.y}
}

func ceiling(value float64, top_value float64) float64{
	if value > top_value {
		value=top_value
	}
	return value
}

func get_local_coordinate_system(eye, look_at, up *vector) (*vector, *vector) {
	a_to_e := eye.sub(look_at)
	w := a_to_e.unit()
	up_X_a_to_e := up.cross(&a_to_e)
	u := up_X_a_to_e.unit()
	v := w.cross(&u)
	return &u, &v
}

func get_scene() (*scene) {
	s := sphere{vector{-25.0, 15.0, -20.0}, 10.0, 0.25, 0, 0, 1.0}
	s2 := sphere{vector{-5.0, -15.0, -15.0}, 15.0, 0.25, 0, 1.0, 0}
	s3 := sphere{vector{5.0, 15.0, -15.0}, 15.0, 0.25, 1.0, 0, 0}
	z := zplane{-30.0, 0.70, 1.0, 1.0, 1.0}
	the_scene:=new(scene)
	the_scene.items=make([]sceneItem,4)
	the_scene.items[0]=&s
	the_scene.items[1]=&s2
	the_scene.items[2]=&s3
	the_scene.items[3]=&z
	return the_scene
}

func get_current_ray (i, j int, the_screen *screen, u, v, look_at, eye *vector) (*ray) {
	cu := (((2.0*float64(i) + 1.0)/(2.0 * float64(the_screen.xres))) - 0.5) * the_screen.w
	cv := (((2.0*float64(j) + 1.0)/(2.0 * float64(the_screen.yres))) - 0.5) * the_screen.h
	ucu := u.scalarMult(cu)
	ucv := v.scalarMult(cv)
	a_plus_ucu := look_at.add(&ucu)
	Pij := a_plus_ucu.add(&ucv)
	e_to_Pij := Pij.sub(eye)
	current_ray := ray{*eye, e_to_Pij.unit()}
	return &current_ray
}

func main() {
	g_screen := screen{100,100,1000,1000}
	g_camera := camera{vector{-100,-100,5}, vector{0,0,0}, vector{0,0,-1}}
	g_light := vector{0.0,100.0,100.0}
	g_ambient := 0.2

	f, err := os.OpenFile("x.png", os.O_CREATE | os.O_WRONLY, 0666)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	m := image.NewRGBA64(image.Rect(0,0,g_screen.xres,g_screen.yres))
	the_scene:=get_scene()
	u, v := get_local_coordinate_system(&g_camera.eye, &g_camera.look_at, &g_camera.up)
	for i:=0; i < g_screen.xres; i++ {
		for j:=0; j < g_screen.yres; j++ {
			current_ray:=get_current_ray(i, j, &g_screen, u, v, &g_camera.look_at, &g_camera.eye)
			// shoot the ray into the scene
			red,green,blue:=the_scene.getColor(current_ray, &g_light, g_ambient)
			m.Set(i,j,color.RGBA64{uint16(65535*red),uint16(65535*green),uint16(65535*blue),65535})
		}
	}
	if err=png.Encode(f,m); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}<commit_msg>switched the zplane to a yplane<commit_after>package main

import "math"
import "fmt"
import "image"
import "os"
import "image/color"
import "image/png"

// vector can represent a point as well, if interpreted as
//  a vector from the origin to a point or 'absolute position vector'.
//  otherwise it represents a 'relative position vector'
type vector struct {
	x, y, z float64
}

type ray struct {
	start vector
	direction vector
}

type camera struct {
	eye vector
	look_at vector
	up vector
}

type screen struct {
	w,h float64
	xres, yres int
}

type sphere struct {
	center vector
	radius,reflectiveness float64
	red,green,blue float64
}

type scene struct {
	items []sceneItem
}

type yplane struct {
	loc, reflectiveness float64
	red,green,blue float64
}

type sceneItem interface {
	intersected(c_ray *ray) (float64, bool)   // returns the t for the intersection, if it occured
	getReflectiveness() (float64)
	getColorRaw() (float64, float64, float64)
	getUnitNormal(point *vector) (*vector)
}

func (y *yplane) getReflectiveness() (float64) {
	return y.reflectiveness
}

func (s *sphere) getReflectiveness() (float64) {
	return s.reflectiveness
}

func (y *yplane) getColorRaw() (float64, float64, float64) {
	return y.red, y.green, y.blue
}

func (s *sphere) getColorRaw() (float64, float64, float64) {
	return s.red, s.green, s.blue
}

func (y *yplane) getUnitNormal(point *vector) (*vector) {
	return &vector{0.0, 1.0, 0.0}
}

func (s *sphere) getUnitNormal(point *vector) (*vector) {
	normal := point.sub(&s.center)
	unormal := normal.unit()
	return &unormal
}

func (the_scene *scene) getColor(c_ray *ray, light *vector, ambient float64) (float64, float64, float64) {
	t_closest := 0.0
	var closest_item sceneItem = nil
	for _, value := range the_scene.items {
		t, is_hit := value.intersected(c_ray)
		if is_hit == false {
			continue
		}
		if closest_item == nil || (t > 0 && t < t_closest) {
			t_closest = t
			closest_item = value
		}
	}

	if closest_item == nil {
		return 0,0,0
	}

	dir := c_ray.direction.scalarMult(t_closest)
	point_on_object:= c_ray.start.add(&dir)

	unormal := closest_item.getUnitNormal(&point_on_object)

	// check for light obstructions
	point_on_object_to_light := light.sub(&point_on_object)
	upoint_on_object_to_light := point_on_object_to_light.unit()

	is_hit:=false
	scale:=0.0
	for _, value := range the_scene.items {
		_, is_hit = value.intersected(&ray{point_on_object, upoint_on_object_to_light})
		if is_hit {
			break
		}
	}

	//calculate the light contribution
	upoint_on_object_to_source := c_ray.direction.scalarMult(-1.0)
	intermediate := unormal.scalarMult(2.0 * upoint_on_object_to_source.dot(unormal))
	reflected := intermediate.sub(&upoint_on_object_to_source)
	ureflected := reflected.unit()

	if is_hit == false {
		scale = ureflected.dot(&upoint_on_object_to_light)
		if scale < 0.0 {
			scale = 0.0
		}
	}

	red,green,blue:=closest_item.getColorRaw()

	red_light := scale*red
	green_light := scale*green
	blue_light := scale*blue

	obj_red:=ceiling(red_light + ambient*red,1.0)
	obj_green:=ceiling(green_light + ambient*green,1.0)
	obj_blue:=ceiling(blue_light + ambient*blue,1.0)

	// send the reflectived ray into the scene
	reflected_red,reflected_green,reflected_blue:=the_scene.getColor(&ray{point_on_object, ureflected},light,ambient)

	reflectiveness := closest_item.getReflectiveness()

	return reflectiveness*reflected_red + (1.0-reflectiveness)*obj_red,
	reflectiveness*reflected_green + (1.0-reflectiveness)*obj_green,
	reflectiveness*reflected_blue + (1.0-reflectiveness)*obj_blue
}

func (y *yplane) intersected(c_ray *ray) (float64, bool)  {
	if c_ray.direction.y == 0.0 {
		return 0.0, false
	}

	t := (y.loc - c_ray.start.y) / c_ray.direction.y
	t = in_buffer(t)
	if t <= 0.0 {
		return 0.0, false
	}

	return t, true
}

var buffer_val float64 = .00001
func in_buffer(val float64) float64{
	if val < buffer_val {
		val = 0.0
	}
	return val
}

func (s *sphere) intersected(c_ray *ray) (float64, bool)  {
	a := c_ray.direction.x * c_ray.direction.x +
		c_ray.direction.y * c_ray.direction.y +
		c_ray.direction.z * c_ray.direction.z
	b := 2.0*((c_ray.start.x-s.center.x)*c_ray.direction.x +
		(c_ray.start.y-s.center.y)*c_ray.direction.y +
		(c_ray.start.z-s.center.z)*c_ray.direction.z)
	c := (c_ray.start.x-s.center.x) * (c_ray.start.x-s.center.x) +
		(c_ray.start.y-s.center.y) * (c_ray.start.y-s.center.y) +
		(c_ray.start.z-s.center.z) * (c_ray.start.z-s.center.z) -
		s.radius * s.radius

	is_hit:=false
	i_test:=b*b-4.0*a*c
	t1,t2,t_closest:=0.0,0.0,0.0
	if i_test >= 0.0 {
		is_hit=true
		t1=(-b+math.Sqrt(i_test))/(2.0*a)
		t2=(-b-math.Sqrt(i_test))/(2.0*a)
		t1=in_buffer(t1)
		t2=in_buffer(t2)
		if t1 <= 0.0 && t2 <= 0.0 {
			is_hit=false  // it hit behind or on the viewer
		}else if t1 > 0.0 && t2 > 0.0 {
			if t1<t2 {
				t_closest=t1
			}else{
				t_closest=t2
			}
		} else if t1 > 0.0 {
			t_closest = t1
		} else if t2 > 0.0 {
			t_closest = t2
		}
	}

	return t_closest, is_hit
}

func (v *vector) sub(v1 *vector) vector {
	return vector{v.x-v1.x, v.y-v1.y, v.z-v1.z}
}

func (v *vector) add(v1 *vector) vector {
	return vector{v.x+v1.x, v.y+v1.y, v.z+v1.z}
}

func (v *vector) scalarMult (c float64) vector {
	return vector{c * v.x, c * v.y, c * v.z}
}

func (v *vector) lengthSq() float64 {
	return v.x * v.x  + v.y * v.y + v.z * v.z
}

func (v *vector) length() float64 {
	return math.Sqrt(v.lengthSq())
}

func (v *vector) unit() vector {
	l := v.length()
	return vector{v.x/l, v.y/l, v.z/l}
}

func (v *vector) dot(v1 *vector) float64 {
	return v.x * v1.x + v.y * v1.y + v.z * v1.z
}

func (v1 *vector) cross(v2 *vector) vector {
	return vector{v1.y * v2.z - v2.y * v1.z,
		v2.x * v1.z - v1.x * v2.z,
		v1.x * v2.y - v2.x * v1.y}
}

func ceiling(value float64, top_value float64) float64{
	if value > top_value {
		value=top_value
	}
	return value
}

func get_local_coordinate_system(eye, look_at, up *vector) (*vector, *vector) {
	a_to_e := eye.sub(look_at)
	w := a_to_e.unit()
	up_X_a_to_e := up.cross(&a_to_e)
	u := up_X_a_to_e.unit()
	v := w.cross(&u)
	return &u, &v
}

func get_scene() (*scene) {
	s := sphere{vector{-25.0, 10.0, -20.0}, 10.0, 0.25, 0, 0, 0.75}
	s2 := sphere{vector{5.0, 15.0, 15.0}, 15.0, 0.25, 0, 0.75, 0}
	s3 := sphere{vector{5.0, 15.0, -15.0}, 15.0, 0.25, 0.75, 0, 0}
	y := yplane{0.0, 0.70, 1.0, 1.0, 1.0}
	the_scene:=new(scene)
	the_scene.items=make([]sceneItem,4)
	the_scene.items[0]=&s
	the_scene.items[1]=&s2
	the_scene.items[2]=&s3
	the_scene.items[3]=&y
	return the_scene
}

func get_current_ray (i, j int, the_screen *screen, u, v, look_at, eye *vector) (*ray) {
	cu := (((2.0*float64(i) + 1.0)/(2.0 * float64(the_screen.xres))) - 0.5) * the_screen.w
	cv := (((2.0*float64(j) + 1.0)/(2.0 * float64(the_screen.yres))) - 0.5) * the_screen.h
	ucu := u.scalarMult(cu)
	ucv := v.scalarMult(cv)
	a_plus_ucu := look_at.add(&ucu)
	Pij := a_plus_ucu.add(&ucv)
	e_to_Pij := Pij.sub(eye)
	current_ray := ray{*eye, e_to_Pij.unit()}
	return &current_ray
}

func main() {
	g_screen := screen{100,100,1000,1000}
	g_camera := camera{vector{-100,50,50}, vector{5,15,-15}, vector{0,1,0}}
	g_light := vector{0.0,100.0,100.0}
	g_ambient := 0.2

	f, err := os.OpenFile("x.png", os.O_CREATE | os.O_WRONLY, 0666)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	m := image.NewRGBA64(image.Rect(0,0,g_screen.xres,g_screen.yres))
	the_scene:=get_scene()
	u, v := get_local_coordinate_system(&g_camera.eye, &g_camera.look_at, &g_camera.up)
	for i:=0; i < g_screen.xres; i++ {
		for j:=0; j < g_screen.yres; j++ {
			current_ray:=get_current_ray(i, j, &g_screen, u, v, &g_camera.look_at, &g_camera.eye)
			// shoot the ray into the scene
			red,green,blue:=the_scene.getColor(current_ray, &g_light, g_ambient)
			m.Set(i,g_screen.yres-j,color.RGBA64{uint16(65535*red),uint16(65535*green),uint16(65535*blue),65535})
		}
	}
	if err=png.Encode(f,m); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}<|endoftext|>


<commit_before>package main

import "math"
import "fmt"
import "image"
import "os"
import "image/color"
import "image/png"

// TODO: see if the circle artifact is a result of saving to a png file

// vector can represent a point as well, if interpreted as
//  a vector from the origin to a point or 'absolute position vector'.
//  otherwise it represents a 'relative position vector'
type vector struct {
	x, y, z float64
}

type ray struct {
	start vector
	direction vector
}

type camera struct {
	eye vector
	look_at vector
	up vector
}

type screen struct {
	w,h float64
	xres, yres int
}

type sphere struct {
	center vector
	radius float64
	red,green,blue uint16
}

func getLightedColor(red, green, blue uint16, t float64, c_ray *ray, light, center *vector) (uint16, uint16, uint16){
	dir := c_ray.direction.scalarMult(t)
	point_on_sphere := c_ray.start.add(&dir)

	normal := point_on_sphere.sub(center)
	unormal := normal.unit()

	point_on_sphere_to_light := light.sub(&point_on_sphere)
	upoint_on_sphere_to_light := point_on_sphere_to_light.unit()

	scale := unormal.dot(&upoint_on_sphere_to_light)
	if scale < 0.0 {
		scale = 0.0
	}

	red_light := uint16(scale*float64(red))
	green_light := uint16(scale*float64(green))
	blue_light := uint16(scale*float64(blue))
	return red_light, green_light, blue_light
}

func (s *sphere) getColor(c_ray *ray, light *vector) (uint16, uint16, uint16, float64, bool) {
	a := c_ray.direction.x * c_ray.direction.x +
		c_ray.direction.y * c_ray.direction.y +
		c_ray.direction.z * c_ray.direction.z
	b := 2.0*((c_ray.start.x-s.center.x)*c_ray.direction.x +
		(c_ray.start.y-s.center.y)*c_ray.direction.y +
		(c_ray.start.z-s.center.z)*c_ray.direction.z)
	c := (c_ray.start.x-s.center.x) * (c_ray.start.x-s.center.x) +
		(c_ray.start.y-s.center.y) * (c_ray.start.y-s.center.y) +
		(c_ray.start.z-s.center.z) * (c_ray.start.z-s.center.z) -
		s.radius * s.radius

	// test with a sphere
	is_hit:=false
	i_test:=b*b-4.0*a*c
	t1,t2,t_closest:=0.0,0.0,0.0
	if i_test > 0.0 {
		is_hit=true
		t1=(-b+math.Sqrt(i_test))/(2.0*a)
		t2=(-b-math.Sqrt(i_test))/(2.0*a)
		if t1 <= 0.0 && t2 <= 0.0 {
			is_hit=false  // it hit behind or on the viewer
		}else if t1 > 0.0 && t2 > 0.0 {
			if t1<t2 {
				t_closest=t1
			}else{
				t_closest=t2
			}
		} else if t1 > 0.0 {
			t_closest = t1
		} else if t2 > 0.0 {
			t_closest = t2
		}
	}

	var red,green,blue uint16
	if is_hit {
		red,green,blue=getLightedColor(s.red,s.green,s.blue,t_closest,c_ray, light, &s.center)
	}

	return red,green,blue,t_closest,is_hit
}

func (v *vector) sub(v1 *vector) vector {
	return vector{v.x-v1.x, v.y-v1.y, v.z-v1.z}
}

func (v *vector) add(v1 *vector) vector {
	return vector{v.x+v1.x, v.y+v1.y, v.z+v1.z}
}

func (v *vector) scalarMult (c float64) vector {
	return vector{c * v.x, c * v.y, c * v.z}
}

func (v *vector) lengthSq() float64 {
	return v.x * v.x  + v.y * v.y + v.z * v.z
}

func (v *vector) length() float64 {
	return math.Sqrt(v.lengthSq())
}

func (v *vector) unit() vector {
	l := v.length()
	return vector{v.x/l, v.y/l, v.z/l}
}

func (v *vector) dot(v1 *vector) float64 {
	return v.x * v1.x + v.y * v1.y + v.z * v1.z
}

func (v1 *vector) cross(v2 *vector) vector {
	return vector{v1.y * v2.z - v2.y * v1.z,
		v2.x * v1.z - v1.x * v2.z,
		v1.x * v2.y - v2.x * v1.y}
}

func main() {
	g_screen := screen{100,100,1000,1000}
	g_camera := camera{vector{0,0,1000}, vector{0,0,0}, vector{0,1,0}}
	g_light := vector{1000,0,1000}

	f, err := os.OpenFile("x.png", os.O_CREATE | os.O_WRONLY, 0666)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	m := image.NewRGBA64(image.Rect(0,0,g_screen.xres,g_screen.yres))

	for i:=0; i < g_screen.xres; i++ {
		for j:=0; j < g_screen.yres; j++ {
			a_to_e := g_camera.eye.sub(&g_camera.look_at)
			w := a_to_e.unit()

			up_X_a_to_e := g_camera.up.cross(&a_to_e)
			u := up_X_a_to_e.unit()
			v := w.cross(&u)

			cu := (((2.0*float64(i) + 1.0)/(2.0 * float64(g_screen.xres))) - 0.5) * g_screen.w
			cv := (((2.0*float64(j) + 1.0)/(2.0 * float64(g_screen.yres))) - 0.5) * g_screen.h

			ucu := u.scalarMult(cu)
			ucv := v.scalarMult(cv)
			a_plus_ucu := g_camera.look_at.add(&ucu)
			Pij := a_plus_ucu.add(&ucv)

			e_to_Pij := Pij.sub(&g_camera.eye)

			current_ray := ray{g_camera.eye, e_to_Pij.unit()}

			// put the sphere at the origin
			s := sphere{vector{5.0, 15.0, 0.0}, 5.0, 0, 0, 65535}
			s2 := sphere{vector{0.0, 0.0, -15.0}, 15.0, 0, 65535, 0}

			red, green, blue, t, is_hit := s.getColor(&current_ray, &g_light)
			red2, green2, blue2, t2, is_hit2 := s2.getColor(&current_ray, &g_light)

			if is_hit && is_hit2 {
				if t<t2 {
					m.Set(i,j,color.RGBA64{red,green,blue,65535})
				}else{
					m.Set(i,j,color.RGBA64{red2,green2,blue2,65535})
				}
			} else if is_hit {
				m.Set(i,j,color.RGBA64{red,green,blue,65535})
			} else if is_hit2 {
				m.Set(i,j,color.RGBA64{red2,green2,blue2,65535})
			} else {
				m.Set(i,j,color.RGBA64{0,0,0,65535})
			}
		}
	}
	if err=png.Encode(f,m); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}<commit_msg>added a sceneItem interface added a scene structure<commit_after>package main

import "math"
import "fmt"
import "image"
import "os"
import "image/color"
import "image/png"

// TODO: see if the circle artifact is a result of saving to a png file
// TODO: is it shading the back of the sphere at that point

// vector can represent a point as well, if interpreted as
//  a vector from the origin to a point or 'absolute position vector'.
//  otherwise it represents a 'relative position vector'
type vector struct {
	x, y, z float64
}

type ray struct {
	start vector
	direction vector
}

type camera struct {
	eye vector
	look_at vector
	up vector
}

type screen struct {
	w,h float64
	xres, yres int
}

type sphere struct {
	center vector
	radius float64
	red,green,blue uint16
}

type scene struct {
	items []sceneItem
}

type sceneItem interface {
	intersected(c_ray *ray) (float64, bool)   // returns the t for the intersection, if it occured
	getColor(t float64, c_ray *ray, light *vector) (uint16, uint16, uint16) // get the color at intersection point
}

func (the_scene *scene) getColor(c_ray *ray, light *vector) (uint16, uint16, uint16) {
	t_closest := 0.0
	var closest_item sceneItem = nil
	for _, value := range the_scene.items {
		t, is_hit := value.intersected(c_ray)
		if is_hit == false {
			continue
		}
		if closest_item == nil || (t > 0 && t < t_closest) {
			t_closest = t
			closest_item = value
		}
	}

	if closest_item == nil {
		return 0.0, 0.0, 0.0
	}

	return closest_item.getColor(t_closest, c_ray, light)
}

func getLightedColor(red, green, blue uint16, t float64, c_ray *ray, light, center *vector) (uint16, uint16, uint16){
	dir := c_ray.direction.scalarMult(t)
	point_on_sphere := c_ray.start.add(&dir)

	normal := point_on_sphere.sub(center)
	unormal := normal.unit()

	point_on_sphere_to_light := light.sub(&point_on_sphere)
	upoint_on_sphere_to_light := point_on_sphere_to_light.unit()

	scale := unormal.dot(&upoint_on_sphere_to_light)
	if scale < 0.0 {
		scale = 0.0
	}

	red_light := uint16(scale*float64(red))
	green_light := uint16(scale*float64(green))
	blue_light := uint16(scale*float64(blue))
	return red_light, green_light, blue_light
}

func (s *sphere) getColor(t float64, c_ray *ray, light *vector) (uint16, uint16, uint16) {
	return getLightedColor(s.red,s.green,s.blue,t,c_ray, light, &s.center)
}

func (s *sphere) intersected(c_ray *ray) (float64, bool)  {
	a := c_ray.direction.x * c_ray.direction.x +
		c_ray.direction.y * c_ray.direction.y +
		c_ray.direction.z * c_ray.direction.z
	b := 2.0*((c_ray.start.x-s.center.x)*c_ray.direction.x +
		(c_ray.start.y-s.center.y)*c_ray.direction.y +
		(c_ray.start.z-s.center.z)*c_ray.direction.z)
	c := (c_ray.start.x-s.center.x) * (c_ray.start.x-s.center.x) +
		(c_ray.start.y-s.center.y) * (c_ray.start.y-s.center.y) +
		(c_ray.start.z-s.center.z) * (c_ray.start.z-s.center.z) -
		s.radius * s.radius

	is_hit:=false
	i_test:=b*b-4.0*a*c
	t1,t2,t_closest:=0.0,0.0,0.0
	if i_test >= 0.0 {
		is_hit=true
		t1=(-b+math.Sqrt(i_test))/(2.0*a)
		t2=(-b-math.Sqrt(i_test))/(2.0*a)
		if t1 <= 0.0 && t2 <= 0.0 {
			is_hit=false  // it hit behind or on the viewer
		}else if t1 > 0.0 && t2 > 0.0 {
			if t1<t2 {
				t_closest=t1
			}else{
				t_closest=t2
			}
		} else if t1 > 0.0 {
			t_closest = t1
		} else if t2 > 0.0 {
			t_closest = t2
		}
	}

	return t_closest, is_hit
}

func (v *vector) sub(v1 *vector) vector {
	return vector{v.x-v1.x, v.y-v1.y, v.z-v1.z}
}

func (v *vector) add(v1 *vector) vector {
	return vector{v.x+v1.x, v.y+v1.y, v.z+v1.z}
}

func (v *vector) scalarMult (c float64) vector {
	return vector{c * v.x, c * v.y, c * v.z}
}

func (v *vector) lengthSq() float64 {
	return v.x * v.x  + v.y * v.y + v.z * v.z
}

func (v *vector) length() float64 {
	return math.Sqrt(v.lengthSq())
}

func (v *vector) unit() vector {
	l := v.length()
	return vector{v.x/l, v.y/l, v.z/l}
}

func (v *vector) dot(v1 *vector) float64 {
	return v.x * v1.x + v.y * v1.y + v.z * v1.z
}

func (v1 *vector) cross(v2 *vector) vector {
	return vector{v1.y * v2.z - v2.y * v1.z,
		v2.x * v1.z - v1.x * v2.z,
		v1.x * v2.y - v2.x * v1.y}
}

func main() {
	g_screen := screen{100,100,1000,1000}
	g_camera := camera{vector{0,0,1000}, vector{0,0,0}, vector{0,1,0}}
	g_light := vector{0,0,1000}

	f, err := os.OpenFile("x.png", os.O_CREATE | os.O_WRONLY, 0666)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	m := image.NewRGBA64(image.Rect(0,0,g_screen.xres,g_screen.yres))

	s := sphere{vector{0.0, 0.0, -15.0}, 10.0, 0, 0, 65535}
	s2 := sphere{vector{5.0, 15.0, 0.0}, 15.0, 0, 65535, 0}
	s3 := sphere{vector{-5.0, -15.0, 0.0}, 15.0, 65535, 0, 0}
	the_scene:=new(scene)
	the_scene.items=make([]sceneItem,3)
	the_scene.items[0]=&s
	the_scene.items[1]=&s2
	the_scene.items[2]=&s3

	for i:=0; i < g_screen.xres; i++ {
		for j:=0; j < g_screen.yres; j++ {
			a_to_e := g_camera.eye.sub(&g_camera.look_at)
			w := a_to_e.unit()

			up_X_a_to_e := g_camera.up.cross(&a_to_e)
			u := up_X_a_to_e.unit()
			v := w.cross(&u)

			cu := (((2.0*float64(i) + 1.0)/(2.0 * float64(g_screen.xres))) - 0.5) * g_screen.w
			cv := (((2.0*float64(j) + 1.0)/(2.0 * float64(g_screen.yres))) - 0.5) * g_screen.h

			ucu := u.scalarMult(cu)
			ucv := v.scalarMult(cv)
			a_plus_ucu := g_camera.look_at.add(&ucu)
			Pij := a_plus_ucu.add(&ucv)

			e_to_Pij := Pij.sub(&g_camera.eye)

			current_ray := ray{g_camera.eye, e_to_Pij.unit()}

			red,green,blue:=the_scene.getColor(&current_ray, &g_light)
			m.Set(i,j,color.RGBA64{red,green,blue,65535})
		}
	}
	if err=png.Encode(f,m); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}<|endoftext|>


<commit_before>package main

import (
	"net/http"

	"github.com/labstack/echo"
	"fmt"
	"os"
	"bufio"
	"io"
	"strings"
	"time"
	"github.com/labstack/echo/middleware"
	"html/template"
	"io/ioutil"
)

func main() {
	// Echo instance
	e := echo.New()

	t := &Template{
		templates: template.Must(template.New("index").Parse(`{{define "index"}}
		{{range .Files}}
		{{.Name}}

		{{end}}
		{{end}}`)),
	}
	e.Renderer = t

	// Middleware
	e.Use(middleware.Recover())

	// Route => handler
	e.GET("/*", handleGet)

	e.POST("/", handlePostPayload)

	// Start server
	e.Logger.Fatal(e.Start(":1323"))
}

func handlePostPayload(c echo.Context) error {
	t := time.Now()
	dir := c.QueryParam("dir")
	if dir != "" {
		err := os.MkdirAll(dir, 0644)
		if err != nil {
			panic("unable to create dir")
		}
	} else {
		dir = t.Format("2006-01-02")
		err := os.MkdirAll(dir, 0644)
		if err != nil {
			panic("unable to create dir")
		}
	}

	fo, err := os.Create("./" + dir + "/" + t.Format("15.04.05.0000"))
	if err != nil {
		panic(err)
	}
	// close fo on exit and check for its returned error
	defer func() {
		if err := fo.Close(); err != nil {
			panic(err)
		}
	}()

	w := bufio.NewWriter(fo)
	defer w.Flush()

	for k, v := range c.Request().Header {
		fmt.Fprintln(w, k + ":", strings.Join(v, ","))
	}

	fmt.Fprintln(w)
	io.Copy(w, c.Request().Body)

	return c.String(http.StatusOK, t.Format("2006-01-02 15:04:05"))
}

type Template struct {
	templates *template.Template
}

func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
	return t.templates.ExecuteTemplate(w, name, data)
}

func handleGet(c echo.Context) error {
	path := c.Param("*")

	if info, err := os.Stat("./" + path); err == nil {
		if info.IsDir() {
			files, err := ioutil.ReadDir("./" + path)
			if err != nil {
				panic("Unable to read directory")
			}

			templData := struct {
				Path string
				Files []os.FileInfo
			}{
				info.Name(),
				files,
			}

			return c.Render(http.StatusOK, "index", templData)
		} else {
			return c.File(path)
		}
	}

	return c.NoContent(http.StatusNotFound)
}<commit_msg>Converted from echo to chi. I found the documentation for chi to more complete as well as more compatible as it uses the standard http.Handler interface<commit_after>package main

import (
	"github.com/pressly/chi"
	"net/http"
	"os"
	"bufio"
	"fmt"
	"strings"
	"io"
	"time"
	"html/template"
	"io/ioutil"
)

func main() {
	r := chi.NewRouter()
	r.Get("/*", showFiles)
	r.Post("/", handlePost)
	http.ListenAndServe(":80", r)
}

func showFiles(w http.ResponseWriter, r *http.Request) {

	t := template.Must(template.New("index").Parse(`{{define "index"}}
		{{range .Files}}
		{{.Name}}

		{{end}}
		{{end}}`))

	path := chi.URLParam(r, "*")

	if info, err := os.Stat("./" + path); err == nil {
		if info.IsDir() {
			files, err := ioutil.ReadDir("./" + path)
			if err != nil {
				panic("Unable to read directory")
			}

			templData := struct {
				Path  string
				Files []os.FileInfo
			}{
				info.Name(),
				files,
			}

			t.Execute(w, templData)
		} else {
			f, _ := ioutil.ReadFile(path)
			w.Write(f)
		}
	} else {
		http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
	}
}

func handlePost(w http.ResponseWriter, r *http.Request) {
	t := time.Now()
	dir := r.URL.Query().Get("dir")
	if dir != "" {
		//Make sure the requested directory is around
		err := os.MkdirAll(dir, 0644)
		if err != nil {
			panic("unable to create dir")
		}
	} else {
		//No directory requested so we give them the default
		dir = t.Format("2006-01-02")
		err := os.MkdirAll(dir, 0644)
		if err != nil {
			panic("unable to create dir")
		}
	}

	//Create file which is named after the create time
	fo, err := os.Create("./" + dir + "/" + t.Format("15.04.05.0000"))
	if err != nil {
		panic(err)
	}
	// close fo on exit and check for its returned error
	defer func() {
		if err := fo.Close(); err != nil {
			panic(err)
		}
	}()

	writer := bufio.NewWriter(fo)
	defer writer.Flush()

	//Write headers to file
	for k, v := range r.Header {
		fmt.Fprintln(writer, k + ":", strings.Join(v, ","))
	}

	fmt.Fprintln(writer)
	//Write request body to file
	io.Copy(writer, r.Body)
	w.Write([]byte(t.Format("2006-01-02 15:04:05")))
}<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"crypto/sha512"
	"flag"
	"fmt"
	"hash"
	"hash/crc32"
	"io"
	"os"
	"runtime"
	"strings"
	"sync"
)

var fHash = flag.String("h", "sha256", "valid hashes: crc32, md5, sha1, sha224, sha256, sha384, sha512")
var fConcurrent = flag.Int("j", runtime.NumCPU()*2, "Maximum number of files processed concurrently.")
var fCheck = flag.Bool("c", false, "Read hash from FILE and verify.")

type fileHash struct {
	fileName         *string
	r                io.ReadCloser
	hash             []byte
	expectedHashType *string
	expecteHash      *string
}

func main() {
	handleFlags()
	in := make(chan fileHash, *fConcurrent*2)
	out := make(chan fileHash, *fConcurrent*2)

	if *fCheck {
		go openFilesForCheck(in)
		go hashFiles(out, in)

		for curResult := range out {
			var computed = fmt.Sprintf("%0x", curResult.hash)
			fmt.Printf("%s %t\n", *curResult.fileName, computed == *curResult.expecteHash)
		}
	} else {
		go openFilesForHashing(in)
		go hashFiles(out, in)

		//Display the hashing results
		for curResult := range out {
			if curResult.fileName == nil {
				fmt.Printf("%0x\n", curResult.hash)
			} else {
				fmt.Printf("%s %0x %s\n", *fHash, curResult.hash, *curResult.fileName)
			}
		}
	}
}

//Setup flags and sanitize user input
func handleFlags() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "%s v1.0 Copyright (c) 2014, Gregory L. Dietsche.\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "Usage of %s: [OPTION]... [FILE]...\n", os.Args[0])
		flag.PrintDefaults()
	}
	flag.Parse()

	if *fConcurrent <= 0 {
		*fConcurrent = 1
	}

	*fHash = strings.ToLower(*fHash)

	runtime.GOMAXPROCS(runtime.NumCPU())
}

func openFilesForCheck(in chan<- fileHash) {
	defer close(in)

	if flag.NArg() != 1 {
		fmt.Fprintln(os.Stderr, "Please specify a file that contains previous hash output from this program.")
		return
	}

	checkFile, err := os.Open(flag.Arg(0))
	if err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		return
	}
	defer checkFile.Close()

	s := bufio.NewScanner(checkFile)
	for s.Scan() {
		var splits = strings.Split(s.Text(), " ")
		if stream, err := os.Open(splits[2]); err == nil {
			in <- fileHash{&splits[2], stream, nil, &splits[0], &splits[1]}
		} else {
			fmt.Fprintln(os.Stderr, err.Error())
		}
	}
}

//Start opening files for processing
func openFilesForHashing(in chan<- fileHash) {
	defer close(in)
	if flag.NArg() == 0 {
		in <- fileHash{nil, os.Stdin, nil, fHash, nil}
	} else {
		for i := range flag.Args() {
			file := flag.Arg(i)
			if stream, err := os.Open(file); err == nil {
				in <- fileHash{&file, stream, nil, fHash, nil}
			} else {
				fmt.Fprintln(os.Stderr, err.Error())
			}
		}
	}
}

func hashFiles(out chan<- fileHash, in <-chan fileHash) {
	defer close(out)
	var wg sync.WaitGroup
	for i := 0; i < *fConcurrent; i++ {
		wg.Add(1)
		go digester(&wg, out, in)
	}
	wg.Wait()
}

func digester(wg *sync.WaitGroup, out chan<- fileHash, streams <-chan fileHash) {
	for file := range streams {
		var hash hash.Hash

		switch *file.expectedHashType {
		case "crc32":
			hash = crc32.NewIEEE()
		case "md5":
			hash = md5.New()
		case "sha1":
			hash = sha1.New()
		case "sha224":
			hash = sha256.New224()
		case "sha256":
			hash = sha256.New()
		case "sha384":
			hash = sha512.New384()
		case "sha512":
			hash = sha512.New()
		default:
			fmt.Fprintf(os.Stderr, "%s: I don't know how to compute a %s hash!\n", *file.fileName, *file.expectedHashType)
			file.r.Close()
			continue
		}

		io.Copy(hash, file.r)
		file.r.Close()
		file.hash = hash.Sum(nil)

		out <- file
	}
	wg.Done()
}
<commit_msg>remove comment<commit_after>package main

import (
	"bufio"
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"crypto/sha512"
	"flag"
	"fmt"
	"hash"
	"hash/crc32"
	"io"
	"os"
	"runtime"
	"strings"
	"sync"
)

var fHash = flag.String("h", "sha256", "valid hashes: crc32, md5, sha1, sha224, sha256, sha384, sha512")
var fConcurrent = flag.Int("j", runtime.NumCPU()*2, "Maximum number of files processed concurrently.")
var fCheck = flag.Bool("c", false, "Read hash from FILE and verify.")

type fileHash struct {
	fileName         *string
	r                io.ReadCloser
	hash             []byte
	expectedHashType *string
	expecteHash      *string
}

func main() {
	handleFlags()
	in := make(chan fileHash, *fConcurrent*2)
	out := make(chan fileHash, *fConcurrent*2)

	if *fCheck {
		go openFilesForCheck(in)
		go hashFiles(out, in)

		for curResult := range out {
			var computed = fmt.Sprintf("%0x", curResult.hash)
			fmt.Printf("%s %t\n", *curResult.fileName, computed == *curResult.expecteHash)
		}
	} else {
		go openFilesForHashing(in)
		go hashFiles(out, in)

		for curResult := range out {
			if curResult.fileName == nil {
				fmt.Printf("%0x\n", curResult.hash)
			} else {
				fmt.Printf("%s %0x %s\n", *fHash, curResult.hash, *curResult.fileName)
			}
		}
	}
}

//Setup flags and sanitize user input
func handleFlags() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "%s v1.0 Copyright (c) 2014, Gregory L. Dietsche.\n", os.Args[0])
		fmt.Fprintf(os.Stderr, "Usage of %s: [OPTION]... [FILE]...\n", os.Args[0])
		flag.PrintDefaults()
	}
	flag.Parse()

	if *fConcurrent <= 0 {
		*fConcurrent = 1
	}

	*fHash = strings.ToLower(*fHash)

	runtime.GOMAXPROCS(runtime.NumCPU())
}

func openFilesForCheck(in chan<- fileHash) {
	defer close(in)

	if flag.NArg() != 1 {
		fmt.Fprintln(os.Stderr, "Please specify a file that contains previous hash output from this program.")
		return
	}

	checkFile, err := os.Open(flag.Arg(0))
	if err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		return
	}
	defer checkFile.Close()

	s := bufio.NewScanner(checkFile)
	for s.Scan() {
		var splits = strings.Split(s.Text(), " ")
		if stream, err := os.Open(splits[2]); err == nil {
			in <- fileHash{&splits[2], stream, nil, &splits[0], &splits[1]}
		} else {
			fmt.Fprintln(os.Stderr, err.Error())
		}
	}
}

//Start opening files for processing
func openFilesForHashing(in chan<- fileHash) {
	defer close(in)
	if flag.NArg() == 0 {
		in <- fileHash{nil, os.Stdin, nil, fHash, nil}
	} else {
		for i := range flag.Args() {
			file := flag.Arg(i)
			if stream, err := os.Open(file); err == nil {
				in <- fileHash{&file, stream, nil, fHash, nil}
			} else {
				fmt.Fprintln(os.Stderr, err.Error())
			}
		}
	}
}

func hashFiles(out chan<- fileHash, in <-chan fileHash) {
	defer close(out)
	var wg sync.WaitGroup
	for i := 0; i < *fConcurrent; i++ {
		wg.Add(1)
		go digester(&wg, out, in)
	}
	wg.Wait()
}

func digester(wg *sync.WaitGroup, out chan<- fileHash, streams <-chan fileHash) {
	for file := range streams {
		var hash hash.Hash

		switch *file.expectedHashType {
		case "crc32":
			hash = crc32.NewIEEE()
		case "md5":
			hash = md5.New()
		case "sha1":
			hash = sha1.New()
		case "sha224":
			hash = sha256.New224()
		case "sha256":
			hash = sha256.New()
		case "sha384":
			hash = sha512.New384()
		case "sha512":
			hash = sha512.New()
		default:
			fmt.Fprintf(os.Stderr, "%s: I don't know how to compute a %s hash!\n", *file.fileName, *file.expectedHashType)
			file.r.Close()
			continue
		}

		io.Copy(hash, file.r)
		file.r.Close()
		file.hash = hash.Sum(nil)

		out <- file
	}
	wg.Done()
}
<|endoftext|>


<commit_before>/*
 * Golpal - Easy to use Golang Eval Library
 * Created by Noval Agung Prayogo <caknopal@gmail.com>
 * http://novalagung.com/
 */

package golpal

import "fmt"
import "os"
import "os/exec"
import "path/filepath"
import "runtime"
import "bytes"
import "time"
import "errors"
import "strings"

const rawExecuteSimple = `package main
import (
	__LIBS__
)
func doStuff() interface{} {
	__CMD__
}
func main() {
	fmt.Println(doStuff())
}`

const rawExecute = `package main
import (
	__LIBS__
)

__CMD__`

const (
	Version                    = "v1.0.0"
	defaultDeleteTemporaryFile = true
	defaultPerm                = 0755
	rawConstLibs               = `__LIBS__`
	rawConstCmd                = `__CMD__`
)

type Golpal struct {
	WillDeleteTemporaryFile bool
	TemporaryFolderName     string

	temporaryFolderPath string
	libs                []string
}

func New() *Golpal {
	g := new(Golpal)
	g.WillDeleteTemporaryFile = defaultDeleteTemporaryFile
	g.prepareDefaultTemporaryFolderName()
	g.prepareDefaultLibs()

	return g
}

func (g *Golpal) prepareDefaultTemporaryFolderName() {
	if runtime.GOOS == "windows" {
		g.TemporaryFolderName = "temp"
	}

	g.TemporaryFolderName = ".temp"
}

func (g *Golpal) prepareDefaultLibs() {
	g.libs = []string{"fmt"}
}

func (g *Golpal) prepareTemporaryFolderPath() {
	basePath, _ := os.Getwd()
	g.temporaryFolderPath = filepath.Join(basePath, g.TemporaryFolderName)
}

func (g *Golpal) prepareTemporaryFile() (string, *os.File, error) {
	g.prepareTemporaryFolderPath()

	filename := fmt.Sprintf("temp-%d.go", time.Now().UnixNano())
	fileLocation := filepath.Join(g.temporaryFolderPath, filename)

	folder, err := os.Open(g.temporaryFolderPath)
	if err != nil {
		if os.IsNotExist(err) {
			if err := os.Mkdir(g.temporaryFolderPath, defaultPerm); err != nil {
				return fileLocation, nil, err
			}
		}
	}
	defer folder.Close()
	file, err := os.OpenFile(fileLocation, os.O_CREATE|os.O_WRONLY, defaultPerm)
	return fileLocation, file, err
}

func (g *Golpal) deleteTemporaryPathIfAllowed() {
	if !g.WillDeleteTemporaryFile {
		return
	}

	g.DeleteTemporaryPath()
}

func (g *Golpal) runCommand(fileLocation string) (string, error) {
	var stdout bytes.Buffer
	var stderr bytes.Buffer
	var cmd *exec.Cmd

	goRun := fmt.Sprintf("go run %s", fileLocation)

	if runtime.GOOS == "windows" {
		cmd = exec.Command("cmd", "/C", goRun)
	} else {
		cmd = exec.Command("bash", "-c", goRun)
	}

	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	if err := cmd.Run(); err != nil {
		errString := err.Error()
		if stderr.Len() > 0 {
			errString = fmt.Sprintf("%s\n%s", errString, stderr.String())
		}

		return "", errors.New(strings.TrimSpace(errString))
	}

	return strings.TrimSpace(stdout.String()), nil
}

func (g *Golpal) renderLibs(cmdString string) string {
	quotedLibString := []string{}

	for _, each := range g.libs {
		if !strings.HasPrefix(`"`, each) {
			each = fmt.Sprintf(`"%s`, each)
		}
		if !strings.HasSuffix(`"`, each) {
			each = fmt.Sprintf(`%s"`, each)
		}

		quotedLibString = append(quotedLibString, each)
	}

	libsString := strings.Join(quotedLibString, "\n")
	res := strings.Replace(cmdString, rawConstLibs, libsString, -1)

	return res
}

func (g *Golpal) containsPrint(cmdString string) bool {
	for _, each := range []string{"Println", "Printf", "Print"} {
		if strings.Contains(cmdString, fmt.Sprintf("fmt.%s", each)) {
			return true
		}
	}

	return false
}

func (g *Golpal) DeleteTemporaryPath() {
	os.RemoveAll(g.temporaryFolderPath)
}

func (g *Golpal) AddLibs(libs ...string) *Golpal {
	for _, lib := range libs {
		lib = strings.TrimSpace(lib)

		if lib == "fmt" || lib == "" {
			continue
		}

		g.libs = append(g.libs, lib)
	}

	return g
}

func (g *Golpal) ExecuteSimple(cmdString string) (string, error) {
	defer g.deleteTemporaryPathIfAllowed()
	cmdString = strings.TrimSpace(cmdString)

	if strings.HasPrefix(cmdString, "package") {
		return "", errors.New("Use `ExecuteRaw()` to exec complete golang file")
	}

	if strings.HasPrefix(cmdString, "func") {
		return "", errors.New("Use `Execute()` to exec code which contains `main()` func")
	}

	if g.containsPrint(cmdString) {
		return "", errors.New("The code cannot contain fmt.Println(), fmt.Printf(), or fmt.Print()")
	}

	fileLocation, file, err := g.prepareTemporaryFile()
	if file != nil {
		defer file.Close()
	}
	if err != nil {
		return "", err
	}

	if len(strings.Split(cmdString, "\n")) == 1 {
		if !strings.HasPrefix(cmdString, "return") {
			cmdString = fmt.Sprintf("return %s", cmdString)
		}
	}

	cmdString = strings.Replace(rawExecuteSimple, rawConstCmd, cmdString, -1)
	cmdString = g.renderLibs(cmdString)

	if _, err := file.WriteString(cmdString); err != nil {
		return "", err
	}

	return g.runCommand(fileLocation)
}

func (g *Golpal) Execute(cmdString string) (string, error) {
	defer g.deleteTemporaryPathIfAllowed()
	cmdString = strings.TrimSpace(cmdString)

	if strings.HasPrefix(cmdString, "package") {
		return "", errors.New("Use `ExecuteRaw()` to exec complete golang file")
	}

	fileLocation, file, err := g.prepareTemporaryFile()
	if file != nil {
		defer file.Close()
	}
	if err != nil {
		return "", err
	}

	cmdString = strings.Replace(rawExecute, rawConstCmd, cmdString, -1)
	cmdString = g.renderLibs(cmdString)

	if _, err := file.WriteString(cmdString); err != nil {
		return "", err
	}

	return g.runCommand(fileLocation)
}

func (g *Golpal) ExecuteRaw(cmdString string) (string, error) {
	defer g.deleteTemporaryPathIfAllowed()
	cmdString = strings.TrimSpace(cmdString)

	fileLocation, file, err := g.prepareTemporaryFile()
	if file != nil {
		defer file.Close()
	}
	if err != nil {
		return "", err
	}

	if _, err := file.WriteString(cmdString); err != nil {
		return "", err
	}

	return g.runCommand(fileLocation)
}
<commit_msg>no message<commit_after>/*
 * Golpal - Easy to use Golang Eval Library
 * Created by Noval Agung Prayogo <caknopal@gmail.com>
 * http://novalagung.com/
 */

package golpal

import "fmt"
import "os"
import "os/exec"
import "path/filepath"
import "runtime"
import "bytes"
import "time"
import "errors"
import "strings"

const rawExecuteSimple = `package main
import (
	__LIBS__
)
func doStuff() interface{} {
	__CMD__
}
func main() {
	fmt.Println(doStuff())
}`

const rawExecute = `package main
import (
	__LIBS__
)

__CMD__`

const (
	Version                               = "v1.0.0"
	defaultWillDeleteTemporaryFile        = true
	defaultPerm                           = 0755
	rawConstLibs                          = `__LIBS__`
	rawConstCmd                           = `__CMD__`
	temporaryFolderPathSubFolder   string = "golpal-files"
)

type Golpal struct {
	WillDeleteTemporaryFile bool
	TemporaryFolderPath     string

	libs []string
}

func New() *Golpal {
	g := new(Golpal).init()

	return g
}

func (g *Golpal) init() *Golpal {
	g.WillDeleteTemporaryFile = defaultWillDeleteTemporaryFile

	// ===== prepare default temporary folder path
	basePath, _ := os.Getwd()
	if runtime.GOOS == "windows" {
		g.TemporaryFolderPath = filepath.Join(basePath, "temp")
	}
	g.TemporaryFolderPath = filepath.Join(basePath, ".temp")

	// ===== prepare default libs
	g.libs = []string{"fmt"}

	return g
}

func (g *Golpal) prepareTemporaryFile() (string, *os.File, error) {
	filename := fmt.Sprintf("temp-%d.go", time.Now().UnixNano())
	fileLocation := filepath.Join(g.getTemporaryFolderExactPath(), filename)

	folder, err := os.Open(g.getTemporaryFolderExactPath())
	if err != nil {
		if os.IsNotExist(err) {
			if err := os.MkdirAll(g.getTemporaryFolderExactPath(), defaultPerm); err != nil {
				return fileLocation, nil, err
			}
		}
	}
	defer folder.Close()

	file, err := os.OpenFile(fileLocation, os.O_CREATE|os.O_WRONLY, defaultPerm)
	return fileLocation, file, err
}

func (g *Golpal) getTemporaryFolderExactPath() string {
	return filepath.Join(g.TemporaryFolderPath, temporaryFolderPathSubFolder)
}

func (g *Golpal) deleteTemporaryPathIfAllowed() {
	if !g.WillDeleteTemporaryFile {
		return
	}

	g.DeleteTemporaryPath()
}

func (g *Golpal) containsPrint(cmdString string) bool {
	for _, each := range []string{"Println", "Printf", "Print"} {
		if strings.Contains(cmdString, fmt.Sprintf("fmt.%s", each)) {
			return true
		}
	}

	return false
}

func (g *Golpal) renderLibs(cmdString string) string {
	quotedLibString := []string{}

	for _, each := range g.libs {
		if !strings.HasPrefix(`"`, each) {
			each = fmt.Sprintf(`"%s`, each)
		}
		if !strings.HasSuffix(`"`, each) {
			each = fmt.Sprintf(`%s"`, each)
		}

		quotedLibString = append(quotedLibString, each)
	}

	libsString := strings.Join(quotedLibString, "\n")
	res := strings.Replace(cmdString, rawConstLibs, libsString, -1)

	return res
}

func (g *Golpal) runCommand(fileLocation string) (string, error) {
	var stdout bytes.Buffer
	var stderr bytes.Buffer
	var cmd *exec.Cmd

	goRun := fmt.Sprintf("go run %s", fileLocation)

	if runtime.GOOS == "windows" {
		cmd = exec.Command("cmd", "/C", goRun)
	} else {
		cmd = exec.Command("bash", "-c", goRun)
	}

	cmd.Stdout = &stdout
	cmd.Stderr = &stderr

	if err := cmd.Run(); err != nil {
		errString := err.Error()
		if stderr.Len() > 0 {
			errString = fmt.Sprintf("%s\n%s", errString, stderr.String())
		}

		return "", errors.New(strings.TrimSpace(errString))
	}

	return strings.TrimSpace(stdout.String()), nil
}

// ===== Public Funcs

func (g *Golpal) DeleteTemporaryPath() *Golpal {
	os.RemoveAll(g.getTemporaryFolderExactPath())
	return g
}

func (g *Golpal) AddLibs(libs ...string) *Golpal {
	for _, lib := range libs {
		lib = strings.TrimSpace(lib)

		if lib == "fmt" || lib == "" {
			continue
		}

		g.libs = append(g.libs, lib)
	}

	return g
}

func (g *Golpal) ExecuteSimple(cmdString string) (string, error) {
	defer g.deleteTemporaryPathIfAllowed()
	cmdString = strings.TrimSpace(cmdString)

	if strings.HasPrefix(cmdString, "package") {
		return "", errors.New("Use `ExecuteRaw()` to exec complete golang file")
	}

	if strings.HasPrefix(cmdString, "func") {
		return "", errors.New("Use `Execute()` to exec code which contains `main()` func")
	}

	if g.containsPrint(cmdString) {
		return "", errors.New("The code cannot contain fmt.Println(), fmt.Printf(), or fmt.Print()")
	}

	fileLocation, file, err := g.prepareTemporaryFile()
	if file != nil {
		defer file.Close()
	}
	if err != nil {
		return "", err
	}

	if len(strings.Split(cmdString, "\n")) == 1 {
		if !strings.HasPrefix(cmdString, "return") {
			cmdString = fmt.Sprintf("return %s", cmdString)
		}
	}

	cmdString = strings.Replace(rawExecuteSimple, rawConstCmd, cmdString, -1)
	cmdString = g.renderLibs(cmdString)

	if _, err := file.WriteString(cmdString); err != nil {
		return "", err
	}

	return g.runCommand(fileLocation)
}

func (g *Golpal) Execute(cmdString string) (string, error) {
	defer g.deleteTemporaryPathIfAllowed()
	cmdString = strings.TrimSpace(cmdString)

	if strings.HasPrefix(cmdString, "package") {
		return "", errors.New("Use `ExecuteRaw()` to exec complete golang file")
	}

	fileLocation, file, err := g.prepareTemporaryFile()
	if file != nil {
		defer file.Close()
	}
	if err != nil {
		return "", err
	}

	cmdString = strings.Replace(rawExecute, rawConstCmd, cmdString, -1)
	cmdString = g.renderLibs(cmdString)

	if _, err := file.WriteString(cmdString); err != nil {
		return "", err
	}

	return g.runCommand(fileLocation)
}

func (g *Golpal) ExecuteRaw(cmdString string) (string, error) {
	defer g.deleteTemporaryPathIfAllowed()
	cmdString = strings.TrimSpace(cmdString)

	fileLocation, file, err := g.prepareTemporaryFile()
	if file != nil {
		defer file.Close()
	}
	if err != nil {
		return "", err
	}

	if _, err := file.WriteString(cmdString); err != nil {
		return "", err
	}

	return g.runCommand(fileLocation)
}
<|endoftext|>


<commit_before>package main

import  (
        "fmt"
        "os"
        "../go-todotxt"
        "github.com/spf13/cobra"
        "os/user"
        "strings"
        "strconv"
        "github.com/rakyll/globalconf"
        "flag"
        "regexp"
        "os/exec"
        "io/ioutil"
)

func extendedLoader(filename string) (todotxt.TaskList, error) {
        usr, err := user.Current()
        if err != nil {
                return nil, err
        }

        filename = strings.Replace(filename, "~", usr.HomeDir, -1)
        tasks := todotxt.LoadTaskList(filename)

        return tasks, nil
}

type flagValue struct {
        str string
}

func (f *flagValue) String() string {
        return f.str
}

func (f *flagValue) Set(value string) error {
        f.str = value
        return nil
}

func newFlagValue(val string) *flagValue {
        return &flagValue{str: val}
}

func main() {

        conf, _ := globalconf.New("gotodo")

        var numtasks bool
        var sortby string
        var finished bool
        var prettyformat string
        var filename string

        var flagFilename = flag.String("file", "", "Location of the todo.txt file.")

        var flags = make(map[string]string)

        var cmdConfig = &cobra.Command{
            Use:   "config [key] [value]",
            Short: "Show and sets config values",
            Long:  `Config can be used to see and also set configuration variables.`,
            Run: func(cmd *cobra.Command, args []string) {
                    if len(args) == 0{
                            fmt.Printf("Available config variables:\n\n")
                            for k := range flags {
                                    fmt.Printf("%s\n", k)
                            }
                    }
                    if len(args) == 1 {
                            val, exists := flags[args[0]]
                            if exists {
                                    fmt.Printf("%s\n", val)
                            } else {
                                    // otherwise exit with non-zero status
                                    os.Exit(1)
                            }
                    }
                    if len(args) == 2 {
                            _, exists := flags[args[0]]
                            if exists {
                                    f := &flag.Flag{Name: args[0], Value: newFlagValue(args[1])}
                                    conf.Set("", f)
                            } else {
                                    os.Exit(1)
                            }
                    }
            },
        }

        var cmdList = &cobra.Command{
            Use:   "list [keyword]",
            Short: "Lists tasks that contain keyword, if any",
            Long:  `List is the most basic command that is used for listing tasks.
                    You can specify a keyword as well as other options.`,
            Run: func(cmd *cobra.Command, args []string) {
                tasks, err := extendedLoader(filename)
                if err != nil {
                        fmt.Println(err)
                        return
                }

                if numtasks {
                    fmt.Println(tasks.Len())
                } else {
                    tasks.Sort(sortby)

                    var filteredTasks todotxt.TaskList
                    for _, task := range tasks {
                        if (!task.Finished() && !finished) ||
                           (task.Finished() && finished) {
                           if (len(args) > 0) {
                                   match, _ := regexp.MatchString(args[0], task.Text())
                                   if match {
                                           filteredTasks = append(filteredTasks, task)
                                   }
                           } else {
                                   filteredTasks = append(filteredTasks, task)
                           }
                        }
                    }

                    for _, task := range filteredTasks {
                            task.SetIdPaddingBy(tasks)
                            fmt.Println(task.PrettyPrint(prettyformat))
                    }
                }
            },
        }
        cmdList.Flags().BoolVarP(&numtasks, "num-tasks", "n", false,
                                 "Show the number of tasks")
        cmdList.Flags().BoolVarP(&finished, "finished", "f", false,
                                 "Show finished tasks")
        cmdList.Flags().StringVarP(&sortby, "sort", "s", "prio",
                                   "Sort tasks by parameter (prio|date|len|prio-rev|date-rev|len-rev|id|rand)")
        cmdList.Flags().StringVarP(&prettyformat, "pretty", "", "%i %p %t",
                                   "Pretty print tasks")

        var cmdAdd = &cobra.Command{
            Use:   "add [task]",
            Short: "Adds a task to the todo list.",
            Long:  `Adds a task to the todo list.`,
            Run: func(cmd *cobra.Command, args []string) {
                tasks, err := extendedLoader(filename)
                if err != nil {
                        fmt.Println(err)
                        return
                }

                task := strings.Join(args, " ")
                tasks.Add(task)

                tasks.Save(filename)
            },
        }

        var nofinishdate bool
        var cmdDone = &cobra.Command{
            Use:   "done [taskid]",
            Short: "Marks task as done.",
            Long:  `Marks task as done.`,
            Run: func(cmd *cobra.Command, args []string) {
                tasks, err := extendedLoader(filename)
                if err != nil {
                        fmt.Println(err)
                        return
                }

                if len(args) < 1 {
                        fmt.Println("So what needs to be done?")
                        return
                }

                taskid, err := strconv.Atoi(args[0])
                if err != nil {
                        fmt.Printf("Do you really consider that a number? %v\n", err)
                        return
                }

                err = tasks.Done(taskid, !nofinishdate)
                if err != nil {
                        fmt.Printf("There was an error %v\n", err)
                }

                tasks.Save(filename)
            },
        }
        cmdDone.Flags().BoolVarP(&nofinishdate, "no-finish-date", "D", false,
                                        "Do not mark finished tasks with date.")

        var cmdArchive = &cobra.Command{
            Use:   "archive [taskid]",
            Short: "Archives task.",
            Long:  `Archives task.`,
            Run: func(cmd *cobra.Command, args []string) {
                tasks, err := extendedLoader(filename)
                if err != nil {
                        fmt.Println(err)
                        return
                }

                if len(args) < 1 {
                        fmt.Println("So what needs to be done?")
                        return
                }

                taskid, err := strconv.Atoi(args[0])
                if err != nil {
                        fmt.Printf("Do you really consider that a number? %v\n", err)
                        return
                }

                fmt.Printf("Archiving task %v\n", taskid)

                tasks.Save(filename)
            },
        }

        var setprio string
        var settodo string
        var cmdSet = &cobra.Command{
            Use:   "set [taskid]",
            Short: "Sets given task's parameters.",
            Long:  `Sets given task's parameters.`,
            Run: func(cmd *cobra.Command, args []string) {
                tasks, err := extendedLoader(filename)
                if err != nil {
                        fmt.Println(err)
                        return
                }

                if len(args) < 1 {
                        fmt.Println("So what do you want to edit?")
                        return
                }

                taskid, err := strconv.Atoi(args[0])
                if err != nil {
                        fmt.Printf("Do you really consider that a number? %v\n", err)
                        return
                }

                if len(setprio) > 0 {
                        tasks[taskid].SetPriority(setprio[0])
                        tasks[taskid].RebuildRawTodo()
                }

                if len(settodo) > 0 {
                        tasks[taskid].SetTodo(settodo)
                        tasks[taskid].RebuildRawTodo()
                }

                tasks.Save(filename)
            },
        }

        var cmdEdit = &cobra.Command{
            Use:   "edit [taskid]",
            Short: "Edit given task",
            Long:  `Edit given task with your prefered editor.`,
            Run: func(cmd *cobra.Command, args []string) {
                tasks, err := extendedLoader(filename)
                if err != nil {
                        fmt.Println(err)
                        return
                }

                if len(args) < 1 {
                        fmt.Println("So what do you want to edit?")
                        return
                }

                taskid, err := strconv.Atoi(args[0])
                if err != nil {
                        fmt.Printf("Do you really consider that a number? %v\n", err)
                        return
                }

                text := tasks[taskid].RawText()

                file, err := ioutil.TempFile(os.TempDir(), "gotodo")
                defer os.Remove(file.Name())

                if err != nil {
                        panic(err)
                }

                e := ioutil.WriteFile(file.Name(), []byte(text), 0644)
                if e != nil {
                        panic(e)
                }

                editor := os.Getenv("EDITOR")
                if len(editor) == 0 {
                        editor = "nano" //FIXME: saner default?
                }

                c := exec.Command(editor, file.Name())

                // nasty hack, see http://stackoverflow.com/a/12089980
                c.Stdin = os.Stdin
                c.Stdout = os.Stdout
                c.Stderr = os.Stderr

                er := c.Run()

                if er != nil {
                        fmt.Println(er.Error())
                        panic(er)
                }

                dat, err := ioutil.ReadFile(file.Name())
                if err != nil {
                        panic(err)
                }

                lines := strings.Split(string(dat), "\n")
                if len (lines) > 0 {
                        if tasks[taskid].RawText() != lines[0] {
                                tasks[taskid] = todotxt.ParseTask(lines[0], taskid)
                                fmt.Printf("Task %d updated to:\n%s\n", taskid, lines[0])
                        }
                }

                tasks.Save(filename)
            },
        }

        cmdSet.PersistentFlags().StringVarP(&setprio, "priority", "p", "",
                                     "Sets task's priority.")
        cmdSet.PersistentFlags().StringVarP(&settodo, "todo", "t", "",
                                     "Sets task's todo.")

        var GotodoCmd = &cobra.Command{
            Use:   "gotodo",
            Short: "Gotodo is a go implementation of todo.txt.",
            Long: `A small, fast and fun implementation of todo.txt`,
            Run: func(cmd *cobra.Command, args []string) {
                cmdList.Run(cmd, nil)
            },
        }

        GotodoCmd.PersistentFlags().StringVarP(&filename, "filename", "", "",
                                     "Load tasks from this file.")

        conf.ParseAll()

        // values here
        flags["file"] = *flagFilename

        // sadly, this is the best we can do right now
        if filename == "" {
                if *flagFilename == "" {
                        filename = "todo.txt"
                } else {
                        filename = *flagFilename
                }
        }

        GotodoCmd.AddCommand(cmdList)
        GotodoCmd.AddCommand(cmdAdd)
        GotodoCmd.AddCommand(cmdDone)
        GotodoCmd.AddCommand(cmdArchive)
        GotodoCmd.AddCommand(cmdSet)
        GotodoCmd.AddCommand(cmdEdit)
        GotodoCmd.AddCommand(cmdConfig)
        GotodoCmd.Execute()
}
<commit_msg>Updated pretty default with color setting<commit_after>package main

import  (
        "fmt"
        "os"
        "../go-todotxt"
        "github.com/spf13/cobra"
        "os/user"
        "strings"
        "strconv"
        "github.com/rakyll/globalconf"
        "flag"
        "regexp"
        "os/exec"
        "io/ioutil"
)

func extendedLoader(filename string) (todotxt.TaskList, error) {
        usr, err := user.Current()
        if err != nil {
                return nil, err
        }

        filename = strings.Replace(filename, "~", usr.HomeDir, -1)
        tasks := todotxt.LoadTaskList(filename)

        return tasks, nil
}

type flagValue struct {
        str string
}

func (f *flagValue) String() string {
        return f.str
}

func (f *flagValue) Set(value string) error {
        f.str = value
        return nil
}

func newFlagValue(val string) *flagValue {
        return &flagValue{str: val}
}

func main() {

        conf, _ := globalconf.New("gotodo")

        var numtasks bool
        var sortby string
        var finished bool
        var prettyformat string
        var filename string

        var flagFilename = flag.String("file", "", "Location of the todo.txt file.")

        var flags = make(map[string]string)

        var cmdConfig = &cobra.Command{
            Use:   "config [key] [value]",
            Short: "Show and sets config values",
            Long:  `Config can be used to see and also set configuration variables.`,
            Run: func(cmd *cobra.Command, args []string) {
                    if len(args) == 0{
                            fmt.Printf("Available config variables:\n\n")
                            for k := range flags {
                                    fmt.Printf("%s\n", k)
                            }
                    }
                    if len(args) == 1 {
                            val, exists := flags[args[0]]
                            if exists {
                                    fmt.Printf("%s\n", val)
                            } else {
                                    // otherwise exit with non-zero status
                                    os.Exit(1)
                            }
                    }
                    if len(args) == 2 {
                            _, exists := flags[args[0]]
                            if exists {
                                    f := &flag.Flag{Name: args[0], Value: newFlagValue(args[1])}
                                    conf.Set("", f)
                            } else {
                                    os.Exit(1)
                            }
                    }
            },
        }

        var cmdList = &cobra.Command{
            Use:   "list [keyword]",
            Short: "Lists tasks that contain keyword, if any",
            Long:  `List is the most basic command that is used for listing tasks.
                    You can specify a keyword as well as other options.`,
            Run: func(cmd *cobra.Command, args []string) {
                tasks, err := extendedLoader(filename)
                if err != nil {
                        fmt.Println(err)
                        return
                }

                if numtasks {
                    fmt.Println(tasks.Len())
                } else {
                    tasks.Sort(sortby)

                    var filteredTasks todotxt.TaskList
                    for _, task := range tasks {
                        if (!task.Finished() && !finished) ||
                           (task.Finished() && finished) {
                           if (len(args) > 0) {
                                   match, _ := regexp.MatchString(args[0], task.Text())
                                   if match {
                                           filteredTasks = append(filteredTasks, task)
                                   }
                           } else {
                                   filteredTasks = append(filteredTasks, task)
                           }
                        }
                    }

                    for _, task := range filteredTasks {
                            task.SetIdPaddingBy(tasks)
                            fmt.Println(task.PrettyPrint(prettyformat))
                    }
                }
            },
        }
        cmdList.Flags().BoolVarP(&numtasks, "num-tasks", "n", false,
                                 "Show the number of tasks")
        cmdList.Flags().BoolVarP(&finished, "finished", "f", false,
                                 "Show finished tasks")
        cmdList.Flags().StringVarP(&sortby, "sort", "s", "prio",
                                   "Sort tasks by parameter (prio|date|len|prio-rev|date-rev|len-rev|id|rand)")
        cmdList.Flags().StringVarP(&prettyformat, "pretty", "", "%c %i %p %t",
                                   "Pretty print tasks")

        var cmdAdd = &cobra.Command{
            Use:   "add [task]",
            Short: "Adds a task to the todo list.",
            Long:  `Adds a task to the todo list.`,
            Run: func(cmd *cobra.Command, args []string) {
                tasks, err := extendedLoader(filename)
                if err != nil {
                        fmt.Println(err)
                        return
                }

                task := strings.Join(args, " ")
                tasks.Add(task)

                tasks.Save(filename)
            },
        }

        var nofinishdate bool
        var cmdDone = &cobra.Command{
            Use:   "done [taskid]",
            Short: "Marks task as done.",
            Long:  `Marks task as done.`,
            Run: func(cmd *cobra.Command, args []string) {
                tasks, err := extendedLoader(filename)
                if err != nil {
                        fmt.Println(err)
                        return
                }

                if len(args) < 1 {
                        fmt.Println("So what needs to be done?")
                        return
                }

                taskid, err := strconv.Atoi(args[0])
                if err != nil {
                        fmt.Printf("Do you really consider that a number? %v\n", err)
                        return
                }

                err = tasks.Done(taskid, !nofinishdate)
                if err != nil {
                        fmt.Printf("There was an error %v\n", err)
                }

                tasks.Save(filename)
            },
        }
        cmdDone.Flags().BoolVarP(&nofinishdate, "no-finish-date", "D", false,
                                        "Do not mark finished tasks with date.")

        var cmdArchive = &cobra.Command{
            Use:   "archive [taskid]",
            Short: "Archives task.",
            Long:  `Archives task.`,
            Run: func(cmd *cobra.Command, args []string) {
                tasks, err := extendedLoader(filename)
                if err != nil {
                        fmt.Println(err)
                        return
                }

                if len(args) < 1 {
                        fmt.Println("So what needs to be done?")
                        return
                }

                taskid, err := strconv.Atoi(args[0])
                if err != nil {
                        fmt.Printf("Do you really consider that a number? %v\n", err)
                        return
                }

                fmt.Printf("Archiving task %v\n", taskid)

                tasks.Save(filename)
            },
        }

        var setprio string
        var settodo string
        var cmdSet = &cobra.Command{
            Use:   "set [taskid]",
            Short: "Sets given task's parameters.",
            Long:  `Sets given task's parameters.`,
            Run: func(cmd *cobra.Command, args []string) {
                tasks, err := extendedLoader(filename)
                if err != nil {
                        fmt.Println(err)
                        return
                }

                if len(args) < 1 {
                        fmt.Println("So what do you want to edit?")
                        return
                }

                taskid, err := strconv.Atoi(args[0])
                if err != nil {
                        fmt.Printf("Do you really consider that a number? %v\n", err)
                        return
                }

                if len(setprio) > 0 {
                        tasks[taskid].SetPriority(setprio[0])
                        tasks[taskid].RebuildRawTodo()
                }

                if len(settodo) > 0 {
                        tasks[taskid].SetTodo(settodo)
                        tasks[taskid].RebuildRawTodo()
                }

                tasks.Save(filename)
            },
        }

        var cmdEdit = &cobra.Command{
            Use:   "edit [taskid]",
            Short: "Edit given task",
            Long:  `Edit given task with your prefered editor.`,
            Run: func(cmd *cobra.Command, args []string) {
                tasks, err := extendedLoader(filename)
                if err != nil {
                        fmt.Println(err)
                        return
                }

                if len(args) < 1 {
                        fmt.Println("So what do you want to edit?")
                        return
                }

                taskid, err := strconv.Atoi(args[0])
                if err != nil {
                        fmt.Printf("Do you really consider that a number? %v\n", err)
                        return
                }

                text := tasks[taskid].RawText()

                file, err := ioutil.TempFile(os.TempDir(), "gotodo")
                defer os.Remove(file.Name())

                if err != nil {
                        panic(err)
                }

                e := ioutil.WriteFile(file.Name(), []byte(text), 0644)
                if e != nil {
                        panic(e)
                }

                editor := os.Getenv("EDITOR")
                if len(editor) == 0 {
                        editor = "nano" //FIXME: saner default?
                }

                c := exec.Command(editor, file.Name())

                // nasty hack, see http://stackoverflow.com/a/12089980
                c.Stdin = os.Stdin
                c.Stdout = os.Stdout
                c.Stderr = os.Stderr

                er := c.Run()

                if er != nil {
                        fmt.Println(er.Error())
                        panic(er)
                }

                dat, err := ioutil.ReadFile(file.Name())
                if err != nil {
                        panic(err)
                }

                lines := strings.Split(string(dat), "\n")
                if len (lines) > 0 {
                        if tasks[taskid].RawText() != lines[0] {
                                tasks[taskid] = todotxt.ParseTask(lines[0], taskid)
                                fmt.Printf("Task %d updated to:\n%s\n", taskid, lines[0])
                        }
                }

                tasks.Save(filename)
            },
        }

        cmdSet.PersistentFlags().StringVarP(&setprio, "priority", "p", "",
                                     "Sets task's priority.")
        cmdSet.PersistentFlags().StringVarP(&settodo, "todo", "t", "",
                                     "Sets task's todo.")

        var GotodoCmd = &cobra.Command{
            Use:   "gotodo",
            Short: "Gotodo is a go implementation of todo.txt.",
            Long: `A small, fast and fun implementation of todo.txt`,
            Run: func(cmd *cobra.Command, args []string) {
                cmdList.Run(cmd, nil)
            },
        }

        GotodoCmd.PersistentFlags().StringVarP(&filename, "filename", "", "",
                                     "Load tasks from this file.")

        conf.ParseAll()

        // values here
        flags["file"] = *flagFilename

        // sadly, this is the best we can do right now
        if filename == "" {
                if *flagFilename == "" {
                        filename = "todo.txt"
                } else {
                        filename = *flagFilename
                }
        }

        GotodoCmd.AddCommand(cmdList)
        GotodoCmd.AddCommand(cmdAdd)
        GotodoCmd.AddCommand(cmdDone)
        GotodoCmd.AddCommand(cmdArchive)
        GotodoCmd.AddCommand(cmdSet)
        GotodoCmd.AddCommand(cmdEdit)
        GotodoCmd.AddCommand(cmdConfig)
        GotodoCmd.Execute()
}
<|endoftext|>


<commit_before>// The govers command edits all packages below the current directory to
// use the given package path prefix.  As with gofmt and gofix, there is
// no backup - you are expected to be using a version control system.
//
// A versioned package path is defined to be any path containing an
// element that matches the regular expression "v[0-9.]+".
//
// Any import that has the given prefix will be changed.
//
// The govers command will also check that all dependencies use the same
// version; if they do not, it will fail and do nothing.
package main

import (
	"bufio"
	"flag"
	"fmt"
	"go/build"
	"go/parser"
	"go/printer"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
)

func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: govers new-package-path\n")
		os.Exit(2)
	}
	flag.Parse()
	if flag.NArg() != 1 {
		flag.Usage()
	}
	cwd, err := os.Getwd()
	if err != nil {
		fatalf("cannot get working directory: %v", err)
	}
	buildCtxt := build.Default
	// BUG we ignore files that are ignored by the current build context
	// if we don't set this flag, but if we do set it, the import fails.
	// The solution is to avoid using build.Import but it's convenient
	// at the moment.
	//	buildCtxt.UseAllFiles = true
	ctxt := &context{
		cwd:           cwd,
		fixPackage:    flag.Arg(0),
		fixPackagePat: pathPat(flag.Arg(0)),
		buildCtxt:     &buildCtxt,
		checked:       make(map[string]bool),
		editPkgs:      make(map[string]*editPkg),
	}
	ctxt.walkDir(cwd)
	for path := range ctxt.editPkgs {
		ctxt.checkPackage(path)
	}
	if ctxt.failed {
		os.Exit(1)
	}
	for path, ep := range ctxt.editPkgs {
		if !ep.needsEdit {
			continue
		}
		changed := false
		for _, file := range ep.goFiles {
			changed = ctxt.changeVersion(file) || changed
		}
		if changed {
			fmt.Printf("%s\n", path)
		}
	}
	if ctxt.failed {
		os.Exit(1)
	}
}

type editPkg struct {
	goFiles   []string
	needsEdit bool
}

type context struct {
	cwd           string
	failed        bool
	fixPackage    string
	fixPackagePat *regexp.Regexp
	buildCtxt     *build.Context
	checked       map[string]bool
	editPkgs      map[string]*editPkg
}

// walkDir walks all directories below path and
// adds any packages to ctxt.editPkgs.
func (ctxt *context) walkDir(path string) {
	entries, err := ioutil.ReadDir(path)
	if err != nil {
		logf("cannot read directory %q: %v", path, err)
		return
	}
	var ep editPkg
	for _, entry := range entries {
		if entry.IsDir() {
			if !strings.HasPrefix(entry.Name(), ".") {
				ctxt.walkDir(filepath.Join(path, entry.Name()))
			}
		} else {
			if strings.HasSuffix(entry.Name(), ".go") {
				ep.goFiles = append(ep.goFiles, filepath.Join(path, entry.Name()))
			}
		}
	}
	pkg, err := ctxt.buildCtxt.Import(".", path, build.FindOnly)
	if err != nil {
		// ignore directories that don't correspond to packages.
		return
	}
	ctxt.editPkgs[pkg.ImportPath] = &ep
}

// checkPackage checks all go files in the given
// package, and all their dependencies.
func (ctxt *context) checkPackage(path string) {
	if path == "C" {
		return
	}
	if ctxt.checked[path] {
		// The package has already been, is or being, checked
		return
	}
	pkg, err := ctxt.buildCtxt.Import(path, ".", 0)
	ctxt.checked[pkg.ImportPath] = true
	if err != nil {
		if _, ok := err.(*build.NoGoError); !ok {
			logf("cannot import %q: %v", path, err)
		}
		return
	}
	ep := ctxt.editPkgs[path]
	for _, impPath := range pkg.Imports {
		if p := ctxt.fixPath(impPath); p != impPath {
			if ep == nil {
				logf("%q uses %q", path, impPath)
				ctxt.failed = true
				continue
			}
			ep.needsEdit = true
			impPath = p
		}
		ctxt.checkPackage(impPath)
	}
}

var printConfig = printer.Config{
	Mode:     printer.TabIndent | printer.UseSpaces,
	Tabwidth: 8,
}

// changeVersion changes the named go file to
// import the new version.
func (ctxt *context) changeVersion(path string) bool {
	fset := token.NewFileSet()
	f, err := parser.ParseFile(fset, path, nil, parser.ParseComments)
	if err != nil {
		logf("cannot parse %q: %v", path, err)
	}
	changed := false
	for _, ispec := range f.Imports {
		impPath, err := strconv.Unquote(ispec.Path.Value)
		if err != nil {
			panic(err)
		}
		if p := ctxt.fixPath(impPath); p != impPath {
			ispec.Path.Value = strconv.Quote(p)
			changed = true
		}
	}
	if !changed {
		return false
	}
	out, err := os.Create(path)
	if err != nil {
		logf("cannot create file: %v", err)
	}
	defer out.Close()
	w := bufio.NewWriter(out)
	if err := printConfig.Fprint(w, fset, f); err != nil {
		logf("cannot write file: %v", err)
	}
	if err := w.Flush(); err != nil {
		logf("cannot write file: %v", err)
	}
	return true
}

func (ctxt *context) fixPath(p string) string {
	loc := ctxt.fixPackagePat.FindStringSubmatchIndex(p)
	if loc == nil {
		return p
	}
	i := loc[3]
	if p[0:i] != ctxt.fixPackage {
		p = ctxt.fixPackage + p[i:]
	}
	return p
}

const versPat = `/v[0-9.]+`

// pathPat returns a pattern that will match any
// package path that's the same except possibly
// the version number.
func pathPat(p string) *regexp.Regexp {
	versRe := regexp.MustCompile(versPat + "(/|$)")
	if !versRe.MatchString(p) {
		fatalf("%q is not versioned", p)
	}
	// Use an intermediate step so that we can use QuoteMeta after
	// matching against versPat.  (versPat won't match quoted
	// metacharacters).
	// Note that  '#' is an invalid character in an import path
	p = versRe.ReplaceAllString(p, "#")
	p = regexp.QuoteMeta(p)
	// BUG doesn't match "foo/v0/v1/bar", but do we care?
	p = "^(" + strings.Replace(p, "#", versPat, -1) + ")(/|$)"
	return regexp.MustCompile(p)
}

func logf(f string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, "govers: %s\n", fmt.Sprintf(f, a...))
}

func fatalf(f string, a ...interface{}) {
	logf(f, a...)
	os.Exit(2)
}
<commit_msg>govers: use /**/ in doc comment<commit_after>/*
The govers command edits all packages below the current directory to
use the given package path prefix.  As with gofmt and gofix, there is
no backup - you are expected to be using a version control system.

A versioned package path is defined to be any path containing an
element that matches the regular expression "v[0-9.]+".

Any import that has the given prefix will be changed.

The govers command will also check that all dependencies use the same
version; if they do not, it will fail and do nothing.
*/
package main

import (
	"bufio"
	"flag"
	"fmt"
	"go/build"
	"go/parser"
	"go/printer"
	"go/token"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
)

func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: govers new-package-path\n")
		os.Exit(2)
	}
	flag.Parse()
	if flag.NArg() != 1 {
		flag.Usage()
	}
	cwd, err := os.Getwd()
	if err != nil {
		fatalf("cannot get working directory: %v", err)
	}
	buildCtxt := build.Default
	// BUG we ignore files that are ignored by the current build context
	// if we don't set this flag, but if we do set it, the import fails.
	// The solution is to avoid using build.Import but it's convenient
	// at the moment.
	//	buildCtxt.UseAllFiles = true
	ctxt := &context{
		cwd:           cwd,
		fixPackage:    flag.Arg(0),
		fixPackagePat: pathPat(flag.Arg(0)),
		buildCtxt:     &buildCtxt,
		checked:       make(map[string]bool),
		editPkgs:      make(map[string]*editPkg),
	}
	ctxt.walkDir(cwd)
	for path := range ctxt.editPkgs {
		ctxt.checkPackage(path)
	}
	if ctxt.failed {
		os.Exit(1)
	}
	for path, ep := range ctxt.editPkgs {
		if !ep.needsEdit {
			continue
		}
		changed := false
		for _, file := range ep.goFiles {
			changed = ctxt.changeVersion(file) || changed
		}
		if changed {
			fmt.Printf("%s\n", path)
		}
	}
	if ctxt.failed {
		os.Exit(1)
	}
}

type editPkg struct {
	goFiles   []string
	needsEdit bool
}

type context struct {
	cwd           string
	failed        bool
	fixPackage    string
	fixPackagePat *regexp.Regexp
	buildCtxt     *build.Context
	checked       map[string]bool
	editPkgs      map[string]*editPkg
}

// walkDir walks all directories below path and
// adds any packages to ctxt.editPkgs.
func (ctxt *context) walkDir(path string) {
	entries, err := ioutil.ReadDir(path)
	if err != nil {
		logf("cannot read directory %q: %v", path, err)
		return
	}
	var ep editPkg
	for _, entry := range entries {
		if entry.IsDir() {
			if !strings.HasPrefix(entry.Name(), ".") {
				ctxt.walkDir(filepath.Join(path, entry.Name()))
			}
		} else {
			if strings.HasSuffix(entry.Name(), ".go") {
				ep.goFiles = append(ep.goFiles, filepath.Join(path, entry.Name()))
			}
		}
	}
	pkg, err := ctxt.buildCtxt.Import(".", path, build.FindOnly)
	if err != nil {
		// ignore directories that don't correspond to packages.
		return
	}
	ctxt.editPkgs[pkg.ImportPath] = &ep
}

// checkPackage checks all go files in the given
// package, and all their dependencies.
func (ctxt *context) checkPackage(path string) {
	if path == "C" {
		return
	}
	if ctxt.checked[path] {
		// The package has already been, is or being, checked
		return
	}
	pkg, err := ctxt.buildCtxt.Import(path, ".", 0)
	ctxt.checked[pkg.ImportPath] = true
	if err != nil {
		if _, ok := err.(*build.NoGoError); !ok {
			logf("cannot import %q: %v", path, err)
		}
		return
	}
	ep := ctxt.editPkgs[path]
	for _, impPath := range pkg.Imports {
		if p := ctxt.fixPath(impPath); p != impPath {
			if ep == nil {
				logf("%q uses %q", path, impPath)
				ctxt.failed = true
				continue
			}
			ep.needsEdit = true
			impPath = p
		}
		ctxt.checkPackage(impPath)
	}
}

var printConfig = printer.Config{
	Mode:     printer.TabIndent | printer.UseSpaces,
	Tabwidth: 8,
}

// changeVersion changes the named go file to
// import the new version.
func (ctxt *context) changeVersion(path string) bool {
	fset := token.NewFileSet()
	f, err := parser.ParseFile(fset, path, nil, parser.ParseComments)
	if err != nil {
		logf("cannot parse %q: %v", path, err)
	}
	changed := false
	for _, ispec := range f.Imports {
		impPath, err := strconv.Unquote(ispec.Path.Value)
		if err != nil {
			panic(err)
		}
		if p := ctxt.fixPath(impPath); p != impPath {
			ispec.Path.Value = strconv.Quote(p)
			changed = true
		}
	}
	if !changed {
		return false
	}
	out, err := os.Create(path)
	if err != nil {
		logf("cannot create file: %v", err)
	}
	defer out.Close()
	w := bufio.NewWriter(out)
	if err := printConfig.Fprint(w, fset, f); err != nil {
		logf("cannot write file: %v", err)
	}
	if err := w.Flush(); err != nil {
		logf("cannot write file: %v", err)
	}
	return true
}

func (ctxt *context) fixPath(p string) string {
	loc := ctxt.fixPackagePat.FindStringSubmatchIndex(p)
	if loc == nil {
		return p
	}
	i := loc[3]
	if p[0:i] != ctxt.fixPackage {
		p = ctxt.fixPackage + p[i:]
	}
	return p
}

const versPat = `/v[0-9.]+`

// pathPat returns a pattern that will match any
// package path that's the same except possibly
// the version number.
func pathPat(p string) *regexp.Regexp {
	versRe := regexp.MustCompile(versPat + "(/|$)")
	if !versRe.MatchString(p) {
		fatalf("%q is not versioned", p)
	}
	// Use an intermediate step so that we can use QuoteMeta after
	// matching against versPat.  (versPat won't match quoted
	// metacharacters).
	// Note that  '#' is an invalid character in an import path
	p = versRe.ReplaceAllString(p, "#")
	p = regexp.QuoteMeta(p)
	// BUG doesn't match "foo/v0/v1/bar", but do we care?
	p = "^(" + strings.Replace(p, "#", versPat, -1) + ")(/|$)"
	return regexp.MustCompile(p)
}

func logf(f string, a ...interface{}) {
	fmt.Fprintf(os.Stderr, "govers: %s\n", fmt.Sprintf(f, a...))
}

func fatalf(f string, a ...interface{}) {
	logf(f, a...)
	os.Exit(2)
}
<|endoftext|>