<commit_before>//
// Copyright (c) 2003-2005 Maxim Sobolev. All rights reserved.
// Copyright (c) 2006-2014 Sippy Software, Inc. All rights reserved.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation and/or
// other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package main

import (
    crand "crypto/rand"
    mrand "math/rand"
    "flag"
    "os"
    "os/signal"
    "runtime"
    "strings"
    "strconv"
    "sync"
    "syscall"
    "time"

    "sippy"
    "sippy/conf"
    "sippy/log"
    "sippy/net"
    "sippy/types"
)

var next_cc_id chan int64

func init() {
    next_cc_id = make(chan int64)
    go func() {
        var id int64 = 1
        for {
            next_cc_id <- id
            id++
        }
    }()
}

type callController struct {
    uaA             sippy_types.UA
    uaO             sippy_types.UA
    lock            *sync.Mutex // this must be a reference to prevent memory leak
    id              int64
    cmap            *callMap
}

func NewCallController(cmap *callMap) *callController {
    self := &callController{
        id              : <-next_cc_id,
        uaO             : nil,
        lock            : new(sync.Mutex),
        cmap            : cmap,
    }
    self.uaA = sippy.NewUA(cmap.sip_tm, cmap.config, cmap.config.nh_addr, self, self.lock, nil)
    self.uaA.SetDeadCb(self.aDead)
    //self.uaA.SetCreditTime(5 * time.Second)
    return self
}

func (self *callController) RecvEvent(event sippy_types.CCEvent, ua sippy_types.UA) {
    if ua == self.uaA {
        if self.uaO == nil {
            if _, ok := event.(*sippy.CCEventTry); ! ok {
                // Some weird event received
                self.uaA.RecvEvent(sippy.NewCCEventDisconnect(nil, event.GetRtime(), ""))
                return
            }
            self.uaO = sippy.NewUA(self.cmap.sip_tm, self.cmap.config, self.cmap.config.nh_addr, self, self.lock, nil)
            self.uaO.SetDeadCb(self.oDead)
            self.uaO.SetRAddr(self.cmap.config.nh_addr)
        }
        self.uaO.RecvEvent(event)
    } else {
        self.uaA.RecvEvent(event)
    }
}

func (self *callController) aDead() {
    self.cmap.Remove(self.id)
}

func (self *callController) oDead() {
    self.cmap.Remove(self.id)
}

func (self *callController) Shutdown() {
    self.uaA.Disconnect(nil)
}

func (self *callController) String() string {
    res := "uaA:" + self.uaA.String() + ", uaO: "
    if self.uaO == nil {
        res += "nil"
    } else {
        res += self.uaO.String()
    }
    return res
}

type callMap struct {
    config *myconfig
    logger          sippy_log.ErrorLogger
    sip_tm          sippy_types.SipTransactionManager
    proxy           sippy_types.StatefulProxy
    ccmap           map[int64]*callController
    ccmap_lock      sync.Mutex
}

func NewCallMap(config *myconfig, logger sippy_log.ErrorLogger) *callMap {
    return &callMap{
        logger          : logger,
        config          : config,
        ccmap           : make(map[int64]*callController),
    }
}

func (self *callMap) OnNewDialog(req sippy_types.SipRequest, tr sippy_types.ServerTransaction) (sippy_types.UA, sippy_types.RequestReceiver, sippy_types.SipResponse) {
    to_body, err := req.GetTo().GetBody(self.config)
    if err != nil {
        self.logger.Error("CallMap::OnNewDialog: #1: " + err.Error())
        return nil, nil, req.GenResponse(500, "Internal Server Error", nil, nil)
    }
    if to_body.GetTag() != "" {
        // Request within dialog, but no such dialog
        return nil, nil, req.GenResponse(481, "Call Leg/Transaction Does Not Exist", nil, nil)
    }
    if req.GetMethod() == "INVITE" {
        // New dialog
        cc := NewCallController(self)
        self.ccmap_lock.Lock()
        self.ccmap[cc.id] = cc
        self.ccmap_lock.Unlock()
        return cc.uaA, cc.uaA, nil
    }
    if req.GetMethod() == "REGISTER" {
        // Registration
        return nil, self.proxy, nil
    }
    if req.GetMethod() == "NOTIFY" || req.GetMethod() == "PING" {
        // Whynot?
        return nil, nil, req.GenResponse(200, "OK", nil, nil)
    }
    return nil, nil, req.GenResponse(501, "Not Implemented", nil, nil)
}

func (self *callMap) Remove(ccid int64) {
    self.ccmap_lock.Lock()
    defer self.ccmap_lock.Unlock()
    delete(self.ccmap, ccid)
}

func (self *callMap) Shutdown() {
    self.ccmap_lock.Lock()
    defer self.ccmap_lock.Unlock()
    for _, cc := range self.ccmap {
        //println(cc.String())
        cc.Shutdown()
    }
}

type myconfig struct {
    sippy_conf.Config

    nh_addr *sippy_net.HostPort
}

func main() {
    runtime.GOMAXPROCS(runtime.NumCPU())
    buf := make([]byte, 8)
    crand.Read(buf)
    var salt int64
    for _, c := range buf {
        salt = (salt << 8) | int64(c)
    }
    mrand.Seed(salt)

    var laddr, nh_addr, logfile string
    var lport int
    var foreground bool

    flag.StringVar(&laddr, "l", "", "Local addr")
    flag.IntVar(&lport, "p", -1, "Local port")
    flag.StringVar(&nh_addr, "n", "", "Next hop address")
    flag.BoolVar(&foreground, "f", false, "Run in foreground")
    flag.StringVar(&logfile, "L", "/var/log/sip.log", "Log file")
    flag.Parse()

    error_logger := sippy_log.NewErrorLogger()
    sip_logger, err := sippy_log.NewSipLogger("b2bua", logfile)
    if err != nil {
        error_logger.Error(err)
        return
    }
    config := &myconfig{
        Config : sippy_conf.NewConfig(error_logger, sip_logger),
        nh_addr      : sippy_net.NewHostPort("192.168.0.102", "5060"), // next hop address
    }
    //config.SetIPV6Enabled(false)
    if nh_addr != "" {
        var parts []string
        var addr string

        if strings.HasPrefix(nh_addr, "[") {
            parts = strings.SplitN(nh_addr, "]", 2)
            addr = parts[0] + "]"
            if len(parts) == 2 {
                parts = strings.SplitN(parts[1], ":", 2)
            }
        } else {
            parts = strings.SplitN(nh_addr, ":", 2)
            addr = parts[0]
        }
        port := "5060"
        if len(parts) == 2 {
            port = parts[1]
        }
        config.nh_addr = sippy_net.NewHostPort(addr, port)
    }
    config.SetMyUAName("Sippy B2BUA (Simple)")
    config.SetAllowFormats([]int{ 0, 8, 18, 100, 101 })
    if laddr != "" {
        config.SetSipAddress(sippy_net.NewMyAddress(laddr))
    } else {
        config.SetSipAddress(config.GetMyAddress())
    }
    if lport > 0 {
        config.SetSipPort(sippy_net.NewMyPort(strconv.Itoa(lport)))
    } else {
        config.SetSipPort(config.GetMyPort())
    }
    cmap := NewCallMap(config, error_logger)
    sip_tm, err := sippy.NewSipTransactionManager(config, cmap)
    if err != nil {
        error_logger.Error(err)
        return
    }
    cmap.sip_tm = sip_tm
    cmap.proxy = sippy.NewStatefulProxy(sip_tm, config.nh_addr, config)
    go sip_tm.Run()

    signal_chan := make(chan os.Signal, 1)
    signal.Notify(signal_chan, syscall.SIGTERM, syscall.SIGINT)
    signal.Ignore(syscall.SIGHUP, syscall.SIGPIPE, syscall.SIGUSR1, syscall.SIGUSR2)
    select {
    case <-signal_chan:
        cmap.Shutdown()
        sip_tm.Shutdown()
        time.Sleep(time.Second)
        break
    }
}
<commit_msg>Make it easier to use the simple_b2bua on a non-default IP address and UDP port.<commit_after>//
// Copyright (c) 2003-2005 Maxim Sobolev. All rights reserved.
// Copyright (c) 2006-2014 Sippy Software, Inc. All rights reserved.
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation and/or
// other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package main

import (
    crand "crypto/rand"
    mrand "math/rand"
    "flag"
    "os"
    "os/signal"
    "runtime"
    "strings"
    "strconv"
    "sync"
    "syscall"
    "time"

    "sippy"
    "sippy/conf"
    "sippy/log"
    "sippy/net"
    "sippy/types"
)

var next_cc_id chan int64

func init() {
    next_cc_id = make(chan int64)
    go func() {
        var id int64 = 1
        for {
            next_cc_id <- id
            id++
        }
    }()
}

type callController struct {
    uaA             sippy_types.UA
    uaO             sippy_types.UA
    lock            *sync.Mutex // this must be a reference to prevent memory leak
    id              int64
    cmap            *callMap
}

func NewCallController(cmap *callMap) *callController {
    self := &callController{
        id              : <-next_cc_id,
        uaO             : nil,
        lock            : new(sync.Mutex),
        cmap            : cmap,
    }
    self.uaA = sippy.NewUA(cmap.sip_tm, cmap.config, cmap.config.nh_addr, self, self.lock, nil)
    self.uaA.SetDeadCb(self.aDead)
    //self.uaA.SetCreditTime(5 * time.Second)
    return self
}

func (self *callController) RecvEvent(event sippy_types.CCEvent, ua sippy_types.UA) {
    if ua == self.uaA {
        if self.uaO == nil {
            if _, ok := event.(*sippy.CCEventTry); ! ok {
                // Some weird event received
                self.uaA.RecvEvent(sippy.NewCCEventDisconnect(nil, event.GetRtime(), ""))
                return
            }
            self.uaO = sippy.NewUA(self.cmap.sip_tm, self.cmap.config, self.cmap.config.nh_addr, self, self.lock, nil)
            self.uaO.SetDeadCb(self.oDead)
            self.uaO.SetRAddr(self.cmap.config.nh_addr)
        }
        self.uaO.RecvEvent(event)
    } else {
        self.uaA.RecvEvent(event)
    }
}

func (self *callController) aDead() {
    self.cmap.Remove(self.id)
}

func (self *callController) oDead() {
    self.cmap.Remove(self.id)
}

func (self *callController) Shutdown() {
    self.uaA.Disconnect(nil)
}

func (self *callController) String() string {
    res := "uaA:" + self.uaA.String() + ", uaO: "
    if self.uaO == nil {
        res += "nil"
    } else {
        res += self.uaO.String()
    }
    return res
}

type callMap struct {
    config *myconfig
    logger          sippy_log.ErrorLogger
    sip_tm          sippy_types.SipTransactionManager
    proxy           sippy_types.StatefulProxy
    ccmap           map[int64]*callController
    ccmap_lock      sync.Mutex
}

func NewCallMap(config *myconfig, logger sippy_log.ErrorLogger) *callMap {
    return &callMap{
        logger          : logger,
        config          : config,
        ccmap           : make(map[int64]*callController),
    }
}

func (self *callMap) OnNewDialog(req sippy_types.SipRequest, tr sippy_types.ServerTransaction) (sippy_types.UA, sippy_types.RequestReceiver, sippy_types.SipResponse) {
    to_body, err := req.GetTo().GetBody(self.config)
    if err != nil {
        self.logger.Error("CallMap::OnNewDialog: #1: " + err.Error())
        return nil, nil, req.GenResponse(500, "Internal Server Error", nil, nil)
    }
    if to_body.GetTag() != "" {
        // Request within dialog, but no such dialog
        return nil, nil, req.GenResponse(481, "Call Leg/Transaction Does Not Exist", nil, nil)
    }
    if req.GetMethod() == "INVITE" {
        // New dialog
        cc := NewCallController(self)
        self.ccmap_lock.Lock()
        self.ccmap[cc.id] = cc
        self.ccmap_lock.Unlock()
        return cc.uaA, cc.uaA, nil
    }
    if req.GetMethod() == "REGISTER" {
        // Registration
        return nil, self.proxy, nil
    }
    if req.GetMethod() == "NOTIFY" || req.GetMethod() == "PING" {
        // Whynot?
        return nil, nil, req.GenResponse(200, "OK", nil, nil)
    }
    return nil, nil, req.GenResponse(501, "Not Implemented", nil, nil)
}

func (self *callMap) Remove(ccid int64) {
    self.ccmap_lock.Lock()
    defer self.ccmap_lock.Unlock()
    delete(self.ccmap, ccid)
}

func (self *callMap) Shutdown() {
    self.ccmap_lock.Lock()
    defer self.ccmap_lock.Unlock()
    for _, cc := range self.ccmap {
        //println(cc.String())
        cc.Shutdown()
    }
}

type myconfig struct {
    sippy_conf.Config

    nh_addr *sippy_net.HostPort
}

func main() {
    runtime.GOMAXPROCS(runtime.NumCPU())
    buf := make([]byte, 8)
    crand.Read(buf)
    var salt int64
    for _, c := range buf {
        salt = (salt << 8) | int64(c)
    }
    mrand.Seed(salt)

    var laddr, nh_addr, logfile string
    var lport int
    var foreground bool

    flag.StringVar(&laddr, "l", "", "Local addr")
    flag.IntVar(&lport, "p", -1, "Local port")
    flag.StringVar(&nh_addr, "n", "", "Next hop address")
    flag.BoolVar(&foreground, "f", false, "Run in foreground")
    flag.StringVar(&logfile, "L", "/var/log/sip.log", "Log file")
    flag.Parse()

    error_logger := sippy_log.NewErrorLogger()
    sip_logger, err := sippy_log.NewSipLogger("b2bua", logfile)
    if err != nil {
        error_logger.Error(err)
        return
    }
    config := &myconfig{
        Config : sippy_conf.NewConfig(error_logger, sip_logger),
        nh_addr      : sippy_net.NewHostPort("192.168.0.102", "5060"), // next hop address
    }
    //config.SetIPV6Enabled(false)
    if nh_addr != "" {
        var parts []string
        var addr string

        if strings.HasPrefix(nh_addr, "[") {
            parts = strings.SplitN(nh_addr, "]", 2)
            addr = parts[0] + "]"
            if len(parts) == 2 {
                parts = strings.SplitN(parts[1], ":", 2)
            }
        } else {
            parts = strings.SplitN(nh_addr, ":", 2)
            addr = parts[0]
        }
        port := "5060"
        if len(parts) == 2 {
            port = parts[1]
        }
        config.nh_addr = sippy_net.NewHostPort(addr, port)
    }
    config.SetMyUAName("Sippy B2BUA (Simple)")
    config.SetAllowFormats([]int{ 0, 8, 18, 100, 101 })
    if laddr != "" {
        config.SetMyAddress(sippy_net.NewMyAddress(laddr))
    }
    config.SetSipAddress(config.GetMyAddress())
    if lport > 0 {
        config.SetMyPort(sippy_net.NewMyPort(strconv.Itoa(lport)))
    }
    config.SetSipPort(config.GetMyPort())
    cmap := NewCallMap(config, error_logger)
    sip_tm, err := sippy.NewSipTransactionManager(config, cmap)
    if err != nil {
        error_logger.Error(err)
        return
    }
    cmap.sip_tm = sip_tm
    cmap.proxy = sippy.NewStatefulProxy(sip_tm, config.nh_addr, config)
    go sip_tm.Run()

    signal_chan := make(chan os.Signal, 1)
    signal.Notify(signal_chan, syscall.SIGTERM, syscall.SIGINT)
    signal.Ignore(syscall.SIGHUP, syscall.SIGPIPE, syscall.SIGUSR1, syscall.SIGUSR2)
    select {
    case <-signal_chan:
        cmap.Shutdown()
        sip_tm.Shutdown()
        time.Sleep(time.Second)
        break
    }
}
<|endoftext|>


<commit_before>package main

import (
	"flag"
	"log"
	"os"

	"github.com/rcrowley/go-tigertonic"
	"github.com/winston-ci/redgreen/api"
)

var listenAddr = flag.String(
	"listen",
	"0.0.0.0:5637",
	"listening address",
)

var peerAddr = flag.String(
	"peerAddr",
	"",
	"address reachable by other nodes",
)

var proleURL = flag.String(
	"proleAddr",
	"http://127.0.0.1:4637",
	"address denoting the prole service",
)

func main() {
	flag.Parse()

	if *peerAddr == "" {
		log.Fatalln("must specify -peerAddr")
	}

	logger := log.New(os.Stdout, "", 0)

	handler := api.New(logger, *peerAddr, *proleURL)

	server := tigertonic.NewServer(*listenAddr, handler)

	err := server.ListenAndServe()
	logger.Fatalln("listen error:", err)
}
<commit_msg>fix -proleURL flag name<commit_after>package main

import (
	"flag"
	"log"
	"os"

	"github.com/rcrowley/go-tigertonic"
	"github.com/winston-ci/redgreen/api"
)

var listenAddr = flag.String(
	"listen",
	"0.0.0.0:5637",
	"listening address",
)

var peerAddr = flag.String(
	"peerAddr",
	"",
	"address reachable by other nodes",
)

var proleURL = flag.String(
	"proleURL",
	"http://127.0.0.1:4637",
	"address denoting the prole service",
)

func main() {
	flag.Parse()

	if *peerAddr == "" {
		log.Fatalln("must specify -peerAddr")
	}

	logger := log.New(os.Stdout, "", 0)

	handler := api.New(logger, *peerAddr, *proleURL)

	server := tigertonic.NewServer(*listenAddr, handler)

	err := server.ListenAndServe()
	logger.Fatalln("listen error:", err)
}
<|endoftext|>


<commit_before>package main

import notify "github.com/mqu/go-notify"
import (
	"fmt"
	"github.com/codegangsta/cli"
	"os"
	"os/exec"
	"regexp"
	"strconv"
)

func main() {
	app := cli.NewApp()
	app.Name = "volumectl"
	app.Usage = "Control master volume from the command line"
	app.Version = "0.0.1"
	app.Commands = []cli.Command{
		{
			Name:  "up",
			Usage: "increase volume (with 2%)",
			Action: func(c *cli.Context) {
				exec.Command("amixer", "sset", "Master", "2%+", "unmute").Run()
				volume := getCurrentVolume()
				showVolumeNotification(volume, false)
			},
		},
		{
			Name:  "down",
			Usage: "decrease volume (with 2%)",
			Action: func(c *cli.Context) {
				exec.Command("amixer", "sset", "Master", "2%-", "unmute").Run()
				volume := getCurrentVolume()
				showVolumeNotification(volume, false)
			},
		},
		{
			Name:  "mute",
			Usage: "mute volume",
			Action: func(c *cli.Context) {
				exec.Command("amixer", "sset", "Master", "mute").Run()
				volume := getCurrentVolume()
				showVolumeNotification(volume, true)
			},
		},
		{
			Name:  "unmute",
			Usage: "unmute volume",
			Action: func(c *cli.Context) {
				exec.Command("amixer", "sset", "Master", "unmute").Run()
				volume := getCurrentVolume()
				showVolumeNotification(volume, false)
			},
		},
		{
			Name:  "toggle",
			Usage: "toggle mute",
			Action: func(c *cli.Context) {
				exec.Command("amixer", "sset", "Master", "toggle").Run()
				volume := getCurrentVolume()
				muted := mutedVolume()
				showVolumeNotification(volume, muted)
			},
		},
		{
			Name:  "set",
			Usage: "set volume to a specific value",
			Action: func(c *cli.Context) {
				exec.Command("amixer", "sset", "Master", c.Args().First()).Run()
				volume := getCurrentVolume()
				showVolumeNotification(volume, false)
			},
		},
	}
	app.Action = func(c *cli.Context) {
		volume := getCurrentVolume()
		mute := "[on]"
		if mutedVolume() {
			mute = "[off]"
		}
		fmt.Println("Volume:", strconv.Itoa(volume)+"%", mute)
	}

	app.Run(os.Args)
}

func getCurrentVolume() int {
	out, err := exec.Command("amixer", "sget", "Master").Output()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Unable to execute amixer command\n")
		return 0
	}

	re := regexp.MustCompile(`\[(\d+)%\]`)
	res := re.FindSubmatch(out)
	if res == nil {
		fmt.Fprintf(os.Stderr, "Unable to parse volume from amixer command output\n")
		return 0
	}

	parsedVolume := string(res[1][:])
	volume, err := strconv.Atoi(parsedVolume)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Unable to convert volume value\n")
		return 0
	}

	return volume
}

func mutedVolume() bool {
	out, err := exec.Command("amixer", "sget", "Master").Output()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Unable to execute amixer command\n")
		return false
	}

	return regexp.MustCompile(`\[(\d+)%\] \[off\]`).Match(out)
}

func showVolumeNotification(volume int, mute bool) {
	notify.Init("Hello World!")
	hello := notify.NotificationNew("Hello World!",
		"This is an example notification.",
		"")

	if hello == nil {
		fmt.Fprintf(os.Stderr, "Unable to create a new notification\n")
		return
	}

	displayVolume := int32(volume)
	iconName := "notification-audio-volume-medium"
	if displayVolume == 0 {
		iconName = "notification-audio-volume-off"
	} else if displayVolume > 70 {
		iconName = "notification-audio-volume-high"
	} else if displayVolume < 30 {
		iconName = "notification-audio-volume-low"
	}

	if mute {
		iconName = "notification-audio-volume-muted"
	}

	hello.Update(" ", "", iconName)
	hello.SetHintInt32("value", displayVolume)
	hello.SetHintString("synchronous", "volume")

	if e := hello.Show(); e != nil {
		fmt.Fprintf(os.Stderr, "%s\n", e.Message())
		return
	}

	notify.UnInit()
}
<commit_msg>Fix imports order<commit_after>package main

import notify "github.com/mqu/go-notify"
import (
	"fmt"
	"os"
	"os/exec"
	"regexp"
	"strconv"

	"github.com/codegangsta/cli"
)

func main() {
	app := cli.NewApp()
	app.Name = "volumectl"
	app.Usage = "Control master volume from the command line"
	app.Version = "0.0.1"
	app.Commands = []cli.Command{
		{
			Name:  "up",
			Usage: "increase volume (with 2%)",
			Action: func(c *cli.Context) {
				exec.Command("amixer", "sset", "Master", "2%+", "unmute").Run()
				volume := getCurrentVolume()
				showVolumeNotification(volume, false)
			},
		},
		{
			Name:  "down",
			Usage: "decrease volume (with 2%)",
			Action: func(c *cli.Context) {
				exec.Command("amixer", "sset", "Master", "2%-", "unmute").Run()
				volume := getCurrentVolume()
				showVolumeNotification(volume, false)
			},
		},
		{
			Name:  "mute",
			Usage: "mute volume",
			Action: func(c *cli.Context) {
				exec.Command("amixer", "sset", "Master", "mute").Run()
				volume := getCurrentVolume()
				showVolumeNotification(volume, true)
			},
		},
		{
			Name:  "unmute",
			Usage: "unmute volume",
			Action: func(c *cli.Context) {
				exec.Command("amixer", "sset", "Master", "unmute").Run()
				volume := getCurrentVolume()
				showVolumeNotification(volume, false)
			},
		},
		{
			Name:  "toggle",
			Usage: "toggle mute",
			Action: func(c *cli.Context) {
				exec.Command("amixer", "sset", "Master", "toggle").Run()
				volume := getCurrentVolume()
				muted := mutedVolume()
				showVolumeNotification(volume, muted)
			},
		},
		{
			Name:  "set",
			Usage: "set volume to a specific value",
			Action: func(c *cli.Context) {
				exec.Command("amixer", "sset", "Master", c.Args().First()).Run()
				volume := getCurrentVolume()
				showVolumeNotification(volume, false)
			},
		},
	}
	app.Action = func(c *cli.Context) {
		volume := getCurrentVolume()
		mute := "[on]"
		if mutedVolume() {
			mute = "[off]"
		}
		fmt.Println("Volume:", strconv.Itoa(volume)+"%", mute)
	}

	app.Run(os.Args)
}

func getCurrentVolume() int {
	out, err := exec.Command("amixer", "sget", "Master").Output()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Unable to execute amixer command\n")
		return 0
	}

	re := regexp.MustCompile(`\[(\d+)%\]`)
	res := re.FindSubmatch(out)
	if res == nil {
		fmt.Fprintf(os.Stderr, "Unable to parse volume from amixer command output\n")
		return 0
	}

	parsedVolume := string(res[1][:])
	volume, err := strconv.Atoi(parsedVolume)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Unable to convert volume value\n")
		return 0
	}

	return volume
}

func mutedVolume() bool {
	out, err := exec.Command("amixer", "sget", "Master").Output()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Unable to execute amixer command\n")
		return false
	}

	return regexp.MustCompile(`\[(\d+)%\] \[off\]`).Match(out)
}

func showVolumeNotification(volume int, mute bool) {
	notify.Init("Hello World!")
	hello := notify.NotificationNew("Hello World!",
		"This is an example notification.",
		"")

	if hello == nil {
		fmt.Fprintf(os.Stderr, "Unable to create a new notification\n")
		return
	}

	displayVolume := int32(volume)
	iconName := "notification-audio-volume-medium"
	if displayVolume == 0 {
		iconName = "notification-audio-volume-off"
	} else if displayVolume > 70 {
		iconName = "notification-audio-volume-high"
	} else if displayVolume < 30 {
		iconName = "notification-audio-volume-low"
	}

	if mute {
		iconName = "notification-audio-volume-muted"
	}

	hello.Update(" ", "", iconName)
	hello.SetHintInt32("value", displayVolume)
	hello.SetHintString("synchronous", "volume")

	if e := hello.Show(); e != nil {
		fmt.Fprintf(os.Stderr, "%s\n", e.Message())
		return
	}

	notify.UnInit()
}
<|endoftext|>


<commit_before>package main

import (
	. "eaciit/wfdemo-git/library/core"
	. "eaciit/wfdemo-git/library/models"
	"eaciit/wfdemo-git/web"
	. "eaciit/wfdemo-git/web/controller"
	"eaciit/wfdemo-git/web/helper"
	"fmt"
	"net/http"
	"strings"

	"github.com/eaciit/acl/v1.0"
	"github.com/eaciit/knot/knot.v1"
	"github.com/eaciit/toolkit"
)

func main() {
	config := new(Configuration)

	config.ID = "port"
	port, err := config.GetPort()
	if err != nil {
		toolkit.Printf("Error get port : %s \n", err.Error())
	}

	ConfigPath = CONFIG_PATH
	prefix := web.AppName

	ServerAddress = toolkit.Sprintf("localhost:%v", toolkit.ToString(port))
	appConf := knot.AppContainerConfig{Address: ServerAddress}
	otherRoutes := map[string]knot.FnContent{
		"/": func(r *knot.WebContext) interface{} {
			sessionid := r.Session("sessionid", "")
			if sessionid == "" {
				http.Redirect(r.Writer, r.Request, fmt.Sprintf("/%s/page/login", prefix), 301)
			} else {
				http.Redirect(r.Writer, r.Request, fmt.Sprintf("/%s/page/dashboard", prefix), 301)
			}

			return true
		},
		"prerequest": func(r *knot.WebContext) interface{} {
			r.Writer.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
			r.Writer.Header().Set("Pragma", "no-cache")
			r.Writer.Header().Set("Expires", "0")

			rURL := r.Request.URL.String()
			sessionid := r.Session("sessionid", "")
			helper.WC = r

			if rURL != "/"+prefix+"/page/login" && rURL != "/"+prefix+"/login/processlogin" {
				active := acl.IsSessionIDActive(toolkit.ToString(sessionid))

				if !active {
					r.SetSession("sessionid", "")
					urlSplit := strings.Split(rURL, "/")
					if urlSplit[2] == "page" {
						http.Redirect(r.Writer, r.Request, fmt.Sprintf("/%s/page/login", prefix), 301)
					} else {
						helper.WC = r
					}
				}
			}
			return true
		},
		"postrequest": func(r *knot.WebContext) interface{} {
			WriteLog(r.Session("sessionid", ""), "access", r.Request.URL.String())
			return true
		},
	}

	knot.DefaultOutputType = knot.OutputTemplate
	knot.StartContainerWithFn(&appConf, otherRoutes)
}
<commit_msg>bug fixing on main.go<commit_after>package main

import (
	. "eaciit/wfdemo-git/library/core"
	. "eaciit/wfdemo-git/library/models"
	"eaciit/wfdemo-git/web"
	. "eaciit/wfdemo-git/web/controller"
	"eaciit/wfdemo-git/web/helper"
	"fmt"
	"net/http"
	"strings"

	"github.com/eaciit/acl/v1.0"
	"github.com/eaciit/knot/knot.v1"
	"github.com/eaciit/toolkit"
)

func main() {
	config := new(Configuration)

	config.ID = "port"
	port, err := config.GetPort()
	if err != nil {
		toolkit.Printf("Error get port : %s \n", err.Error())
	}

	ConfigPath = CONFIG_PATH
	prefix := web.AppName

	ServerAddress = toolkit.Sprintf("localhost:%v", toolkit.ToString(port))
	appConf := knot.AppContainerConfig{Address: ServerAddress}
	otherRoutes := map[string]knot.FnContent{
		"/": func(r *knot.WebContext) interface{} {
			sessionid := r.Session("sessionid", "")
			if sessionid == "" {
				http.Redirect(r.Writer, r.Request, fmt.Sprintf("/%s/page/login", prefix), 301)
			} else {
				http.Redirect(r.Writer, r.Request, fmt.Sprintf("/%s/page/dashboard", prefix), 301)
			}

			return true
		},
		"prerequest": func(r *knot.WebContext) interface{} {
			r.Writer.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
			r.Writer.Header().Set("Pragma", "no-cache")
			r.Writer.Header().Set("Expires", "0")

			rURL := r.Request.URL.String()
			sessionid := r.Session("sessionid", "")
			helper.WC = r

			if rURL != "/"+prefix+"/page/login" && rURL != "/"+prefix+"/login/processlogin" {
				active := acl.IsSessionIDActive(toolkit.ToString(sessionid))

				if !active {
					r.SetSession("sessionid", "")
					urlSplit := strings.Split(rURL, "/")

					if len(urlSplit) > 2 {
						if urlSplit[2] == "page" {
							http.Redirect(r.Writer, r.Request, fmt.Sprintf("/%s/page/login", prefix), 301)
						} else {
							helper.WC = r
						}
					} else {
						http.Redirect(r.Writer, r.Request, fmt.Sprintf("/%s/page/login", prefix), 301)
					}
				}
			}
			return true
		},
		"postrequest": func(r *knot.WebContext) interface{} {
			WriteLog(r.Session("sessionid", ""), "access", r.Request.URL.String())
			return true
		},
	}

	knot.DefaultOutputType = knot.OutputTemplate
	knot.StartContainerWithFn(&appConf, otherRoutes)
}
<|endoftext|>


<commit_before>package main

import (
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base32"
	"fmt"
	"os"
	"strings"
	"time"
)

func toBytes(value int64) []byte {
	var result []byte
	mask := int64(0xFF)
	shifts := [8]uint16{56, 48, 40, 32, 24, 16, 8, 0}
	for _, shift := range shifts {
		result = append(result, byte((value>>shift)&mask))
	}
	return result
}

func toUint32(bytes []byte) uint32 {
	return (uint32(bytes[0]) << 24) + (uint32(bytes[1]) << 16) +
		(uint32(bytes[2]) << 8) + uint32(bytes[3])
}

func oneTimePassword(key []byte, value []byte) uint32 {
	// sign the value using HMAC-SHA1
	hmacSha1 := hmac.New(sha1.New, key)
	hmacSha1.Write(value)
	hash := hmacSha1.Sum(nil)

	// We're going to use a subset of the generated hash.
	// Using the last nibble (half-byte) to choose the index to start from.
	// This number is always appropriate as it's maximum decimal 15, the hash will
	// have the maximum index 19 (20 bytes of SHA1) and we need 4 bytes.
	offset := hash[len(hash)-1] & 0x0F

	// get a 32-bit (4-byte) chunk from the hash starting at offset
	hashParts := hash[offset : offset+4]

	// ignore the most significant bit as per RFC 4226
	hashParts[0] = hashParts[0] & 0x7F

	number := toUint32(hashParts)

	// size to 6 digits
	// one million is the first number with 7 digits so the remainder
	// of the division will always return < 7 digits
	pwd := number % 1000000

	return pwd
}

// all []byte in this program are treated as Big Endian
func main() {
	if len(os.Args) < 2 {
		fmt.Fprintln(os.Stderr, "must specify key to use")
		os.Exit(1)
	}

	input := os.Args[1]

	// decode the key from the first argument
	inputNoSpaces := strings.Replace(input, " ", "", -1)
	inputNoSpacesUpper := strings.ToUpper(inputNoSpaces)
	key, err := base32.StdEncoding.DecodeString(inputNoSpacesUpper)
	if err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		os.Exit(1)
	}

	// generate a one-time password using the time at 30-second intervals
	epochSeconds := time.Now().Unix()
	pwd := oneTimePassword(key, toBytes(epochSeconds/30))

	secondsRemaining := 30 - (epochSeconds % 30)
	fmt.Printf("%d (%d second(s) remaining)\n", pwd, secondsRemaining)
}
<commit_msg>fixed formatting of integers to allow for leading 0's<commit_after>package main

import (
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base32"
	"fmt"
	"os"
	"strings"
	"time"
)

func toBytes(value int64) []byte {
	var result []byte
	mask := int64(0xFF)
	shifts := [8]uint16{56, 48, 40, 32, 24, 16, 8, 0}
	for _, shift := range shifts {
		result = append(result, byte((value>>shift)&mask))
	}
	return result
}

func toUint32(bytes []byte) uint32 {
	return (uint32(bytes[0]) << 24) + (uint32(bytes[1]) << 16) +
		(uint32(bytes[2]) << 8) + uint32(bytes[3])
}

func oneTimePassword(key []byte, value []byte) uint32 {
	// sign the value using HMAC-SHA1
	hmacSha1 := hmac.New(sha1.New, key)
	hmacSha1.Write(value)
	hash := hmacSha1.Sum(nil)

	// We're going to use a subset of the generated hash.
	// Using the last nibble (half-byte) to choose the index to start from.
	// This number is always appropriate as it's maximum decimal 15, the hash will
	// have the maximum index 19 (20 bytes of SHA1) and we need 4 bytes.
	offset := hash[len(hash)-1] & 0x0F

	// get a 32-bit (4-byte) chunk from the hash starting at offset
	hashParts := hash[offset : offset+4]

	// ignore the most significant bit as per RFC 4226
	hashParts[0] = hashParts[0] & 0x7F

	number := toUint32(hashParts)

	// size to 6 digits
	// one million is the first number with 7 digits so the remainder
	// of the division will always return < 7 digits
	pwd := number % 1000000

	return pwd
}

// all []byte in this program are treated as Big Endian
func main() {
	if len(os.Args) < 2 {
		fmt.Fprintln(os.Stderr, "must specify key to use")
		os.Exit(1)
	}

	input := os.Args[1]

	// decode the key from the first argument
	inputNoSpaces := strings.Replace(input, " ", "", -1)
	inputNoSpacesUpper := strings.ToUpper(inputNoSpaces)
	key, err := base32.StdEncoding.DecodeString(inputNoSpacesUpper)
	if err != nil {
		fmt.Fprintln(os.Stderr, err.Error())
		os.Exit(1)
	}

	// generate a one-time password using the time at 30-second intervals
	epochSeconds := time.Now().Unix()
	pwd := oneTimePassword(key, toBytes(epochSeconds/30))

	secondsRemaining := 30 - (epochSeconds % 30)
	fmt.Printf("%06d (%d second(s) remaining)\n", pwd, secondsRemaining)
}
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"os"
	"runtime"

	"github.com/codegangsta/cli"
	"github.com/mitchellh/go-homedir"
	"github.com/skratchdot/open-golang/open"
)

var (
	// exitCode to terminate.
	exitCode = 0

	// Default endpoint.
	endpoint = "http://upload.gyazo.com/upload.cgi"
)

func main() {
	defer os.Exit(exitCode)

	app := cli.NewApp()
	app.Name = "gyazo"
	app.Version = Version
	app.Usage = "Gyazo command-line uploader"
	app.Author = "Tomohiro TAIRA"
	app.Email = "tomohiro.t@gmail.com"
	app.Action = upload
	app.Run(os.Args)
}

// Set the endpoint of Gyazo API.
func init() {
	if os.Getenv("GYAZO_SERVER_URL") != "" {
		endpoint = os.Getenv("GYAZO_SERVER_URL")
	} else if os.Getenv("GYAZO_ACCESS_TOKEN") != "" {
		endpoint = "https://upload.gyazo.com/api/upload"
	}
}

// Image represents a uploaded image on the Gyazo server.
//
// Gyazo API docs: https://gyazo.com/api/docs/image
type Image struct {
	ID           string `json:"image_id"`
	PermalinkURL string `json:"permalink_url"`
	ThumbURL     string `json:"thumb_url"`
	URL          string `json:"url"`
	Type         string `json:"type"`
}

// Upload a new image to a Gyazo server from the specified local image file.
//
// Gyazo API docs: https://gyazo.com/api/docs/image
func upload(c *cli.Context) {
	if len(c.Args()) == 0 {
		fmt.Fprintln(os.Stderr, "Try `gyazo --help` for more information")
		exitCode = 1
		return
	}

	filename := c.Args().First()
	content, err := os.Open(filename)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to open and read %s\n", filename)
		return
	}
	defer content.Close()

	// Create multipart/form-data
	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)

	part, err := writer.CreateFormFile("imagedata", filename)
	if err != nil {
		exitCode = 1
		return
	}

	if _, err = io.Copy(part, content); err != nil {
		exitCode = 1
		return
	}

	if os.Getenv("GYAZO_ACCESS_TOKEN") != "" {
		writer.WriteField("access_token", os.Getenv("GYAZO_ACCESS_TOKEN"))
	} else {
		writer.WriteField("id", gyazoID())
	}

	err = writer.Close()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to create multipart/data: %s\n", err)
		exitCode = 1
		return
	}

	res, err := http.Post(endpoint, writer.FormDataContentType(), body)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to upload: %s\n", err)
		exitCode = 1
		return
	}
	defer res.Body.Close()

	url, err := imageURL(res)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Response error: %s\n", err)
		exitCode = 1
		return
	}

	fmt.Println(url)
	err = open.Run(url)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to open by default browser: %s\n", err)
	}
}

// imageURL returns url of uploaded image.
func imageURL(r *http.Response) (string, error) {
	var url = ""
	if os.Getenv("GYAZO_ACCESS_TOKEN") != "" {
		image := Image{}
		if err := json.NewDecoder(r.Body).Decode(&image); err != nil {
			return url, err
		}

		url = image.PermalinkURL
	} else {
		id := r.Header.Get("X-Gyazo-Id")
		if err := storeGyazoID(id); err != nil {
			fmt.Fprintf(os.Stderr, "Failed to store Gyazo ID: %s\n", err)
		}

		body, err := ioutil.ReadAll(r.Body)
		if err != nil {
			return url, err
		}

		url = string(body)
	}

	return url, nil
}

// gyazoID returns Gyazo ID from stored file.
func gyazoID() string {
	var id = ""
	body, err := ioutil.ReadFile(gyazoIDPath())
	if err != nil {
		return id
	}

	id = string(body)
	return id
}

// storeGyazoID stores Gyazo ID to file.
func storeGyazoID(id string) error {
	var err error
	buf := bytes.NewBufferString(id)
	err = ioutil.WriteFile(gyazoIDPath(), buf.Bytes(), 0644)
	if err != nil {
		return err
	}
	return err
}

// gyazoIDPath returns path of Gyazo ID file on local filesystem.
func gyazoIDPath() string {
	homedir, _ := homedir.Dir()

	var path = ""
	switch runtime.GOOS {
	case "darwin":
		path = fmt.Sprintf("%s/Library/Gyazo/id", homedir)
	case "linux":
		path = fmt.Sprintf("%s/.gyazo.id", homedir)
	case "windows":
		path = fmt.Sprintf("%s\\Gyazo\\id.txt", os.Getenv("APPDATA"))
	}

	return path
}
<commit_msg>Not store id when id is empty<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"os"
	"runtime"

	"github.com/codegangsta/cli"
	"github.com/mitchellh/go-homedir"
	"github.com/skratchdot/open-golang/open"
)

var (
	// exitCode to terminate.
	exitCode = 0

	// Default endpoint.
	endpoint = "http://upload.gyazo.com/upload.cgi"
)

func main() {
	defer os.Exit(exitCode)

	app := cli.NewApp()
	app.Name = "gyazo"
	app.Version = Version
	app.Usage = "Gyazo command-line uploader"
	app.Author = "Tomohiro TAIRA"
	app.Email = "tomohiro.t@gmail.com"
	app.Action = upload
	app.Run(os.Args)
}

// Set the endpoint of Gyazo API.
func init() {
	if os.Getenv("GYAZO_SERVER_URL") != "" {
		endpoint = os.Getenv("GYAZO_SERVER_URL")
	} else if os.Getenv("GYAZO_ACCESS_TOKEN") != "" {
		endpoint = "https://upload.gyazo.com/api/upload"
	}
}

// Image represents a uploaded image on the Gyazo server.
//
// Gyazo API docs: https://gyazo.com/api/docs/image
type Image struct {
	ID           string `json:"image_id"`
	PermalinkURL string `json:"permalink_url"`
	ThumbURL     string `json:"thumb_url"`
	URL          string `json:"url"`
	Type         string `json:"type"`
}

// Upload a new image to a Gyazo server from the specified local image file.
//
// Gyazo API docs: https://gyazo.com/api/docs/image
func upload(c *cli.Context) {
	if len(c.Args()) == 0 {
		fmt.Fprintln(os.Stderr, "Try `gyazo --help` for more information")
		exitCode = 1
		return
	}

	filename := c.Args().First()
	content, err := os.Open(filename)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to open and read %s\n", filename)
		return
	}
	defer content.Close()

	// Create multipart/form-data
	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)

	part, err := writer.CreateFormFile("imagedata", filename)
	if err != nil {
		exitCode = 1
		return
	}

	if _, err = io.Copy(part, content); err != nil {
		exitCode = 1
		return
	}

	if os.Getenv("GYAZO_ACCESS_TOKEN") != "" {
		writer.WriteField("access_token", os.Getenv("GYAZO_ACCESS_TOKEN"))
	} else {
		writer.WriteField("id", gyazoID())
	}

	err = writer.Close()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to create multipart/data: %s\n", err)
		exitCode = 1
		return
	}

	res, err := http.Post(endpoint, writer.FormDataContentType(), body)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to upload: %s\n", err)
		exitCode = 1
		return
	}
	defer res.Body.Close()

	url, err := imageURL(res)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Response error: %s\n", err)
		exitCode = 1
		return
	}

	fmt.Println(url)
	err = open.Run(url)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to open by default browser: %s\n", err)
	}
}

// imageURL returns url of uploaded image.
func imageURL(r *http.Response) (string, error) {
	var url = ""
	if os.Getenv("GYAZO_ACCESS_TOKEN") != "" {
		image := Image{}
		if err := json.NewDecoder(r.Body).Decode(&image); err != nil {
			return url, err
		}

		url = image.PermalinkURL
	} else {
		id := r.Header.Get("X-Gyazo-Id")
		if err := storeGyazoID(id); err != nil {
			fmt.Fprintf(os.Stderr, "Failed to store Gyazo ID: %s\n", err)
		}

		body, err := ioutil.ReadAll(r.Body)
		if err != nil {
			return url, err
		}

		url = string(body)
	}

	return url, nil
}

// gyazoID returns Gyazo ID from stored file.
func gyazoID() string {
	var id = ""
	body, err := ioutil.ReadFile(gyazoIDPath())
	if err != nil {
		return id
	}

	id = string(body)
	return id
}

// storeGyazoID stores Gyazo ID to file.
func storeGyazoID(id string) error {
	var err error
	if id == "" {
		return err
	}

	buf := bytes.NewBufferString(id)
	err = ioutil.WriteFile(gyazoIDPath(), buf.Bytes(), 0644)
	if err != nil {
		return err
	}
	return err
}

// gyazoIDPath returns path of Gyazo ID file on local filesystem.
func gyazoIDPath() string {
	homedir, _ := homedir.Dir()

	var path = ""
	switch runtime.GOOS {
	case "darwin":
		path = fmt.Sprintf("%s/Library/Gyazo/id", homedir)
	case "linux":
		path = fmt.Sprintf("%s/.gyazo.id", homedir)
	case "windows":
		path = fmt.Sprintf("%s\\Gyazo\\id.txt", os.Getenv("APPDATA"))
	}

	return path
}
<|endoftext|>


<commit_before>package main

// TODO: refactor

import (
	"bufio"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"strings"

	"github.com/elpinal/coco3/eval"
	"github.com/elpinal/coco3/parser"
	"github.com/mattn/go-runewidth"
)

var prompt = "; "

type history struct {
	lines [][]rune
	i     int
}

func main() {
	var command = flag.String("c", "", "take first argument as a command to execute")
	flag.Parse()
	if *command != "" {
		if err := execute([]byte(*command)); err != nil {
			fmt.Fprintln(os.Stderr, err)
		}
		return
	}
	var hist history
	for {
		if err := loop(&hist); err != nil {
			fmt.Fprintln(os.Stderr, err)
		}
	}
}

const (
	CharCtrlA = iota + 1
	CharCtrlB
	CharCtrlC
	CharCtrlD
	CharCtrlE
	CharCtrlF
	CharCtrlG
	CharCtrlH
	CharCtrlI
	CharCtrlJ
	CharCtrlK
	CharCtrlL
	CharCtrlM
	CharCtrlN
	CharCtrlO
	CharCtrlP
	CharCtrlQ
	CharCtrlR
	CharCtrlS
	CharCtrlT
	CharCtrlU
	CharCtrlV
	CharCtrlW
	CharCtrlX
	CharCtrlY
	CharCtrlZ
	CharEscape

	CharBackspace = 127
)

func loop(hist *history) error {
	fmt.Print("\r\033[J")
	fmt.Print("\n")
	fmt.Print("-- INSERT --")
	fmt.Print("\033[A")
	fmt.Print("\r")
	fmt.Print(prompt)

	rd := NewReader(os.Stdin)
	lines := make([][]rune, len(hist.lines))
	copy(lines, hist.lines)
	cl := &commandline{
		w: bufio.NewWriter(os.Stdout),
		hist: history{
			lines: lines,
			i:     hist.i,
		},
		mode: insertMode,
	}
	state, err := enterRowMode()
	if err != nil {
		return err
	}
LOOP:
	for {
		ch, err := rd.Read()
		if err != nil {
			return err
		}
		switch cl.mode {
		case normalMode:
			switch ch {
			case CharCtrlM:
				break LOOP
			case 'h':
				cl.toLeft()
			case 'l':
				cl.toRight()
			case '0':
				cl.toTheFirst()
			case '^':
				cl.toTheFirstNonBlank()
			case '$':
				cl.toTheEnd()
			case 'k':
				cl.prevHistory()
			case 'j':
				cl.nextHistory()
			case 'w':
				cl.wordForward()
			case 'W':
				cl.wordForwardNonBlank()
			case 'b':
				cl.wordBackward()
			case 'B':
				cl.wordBackwardNonBlank()
			case 'a':
				cl.moveForward()
				cl.mode = insertMode
			case 'i':
				cl.mode = insertMode
			case 'x':
				cl.deleteUnder()
			case 'c', 'd', 'y':
				cl.mode = operatorPendingMode
				cl.pending = ch
			case 'g':
				ch1, err := rd.Read()
				if err != nil {
					return err
				}
				switch ch1 {
				case '_':
					cl.toTheLastNonBlank()
				}
			default:
			}
		case insertMode:
			switch ch {
			case CharCtrlM:
				break LOOP
			case CharEscape:
				cl.moveBackward()
				cl.mode = normalMode
			case CharBackspace:
				cl.deleteChar()
			case CharCtrlI:
				cl.complete()
				if cl.compl != nil {
					err := cl.completeMode(rd)
					if err != nil {
						return err
					}
				}
			default:
				cl.appendChar(ch)
			}
		case operatorPendingMode:
			switch ch {
			case 'h':
				from := cl.index
				cl.toLeft()
				to := cl.index
				cl.operate(cl.pending, from, to)
			case 'l':
				from := cl.index
				cl.toRight()
				to := cl.index
				cl.operate(cl.pending, from, to)
			case cl.pending:
				from := 0
				to := len(cl.buf)
				cl.operate(cl.pending, from, to)
			default:
				cl.mode = normalMode
			}
		}
		cl.refresh()
	}
	cl.w.WriteByte('\n')
	cl.w.WriteString("\r\033[K")
	cl.w.Flush()
	err = exitRowMode(state)
	if err != nil {
		return err
	}
	if len(hist.lines) == 0 || string(hist.lines[hist.i-1]) != string(cl.buf) {
		hist.lines = append(hist.lines, cl.buf)
		hist.i++
	}
	return execute([]byte(string(cl.buf)))
}

func execute(b []byte) error {
	f, err := parser.ParseSrc(b)
	if err != nil {
		return err
	}
	return eval.Eval(f.Lines)
}

type commandline struct {
	w     *bufio.Writer
	buf   []rune
	index int

	hist history

	mode    mode
	pending rune

	compl     []string
	maxLength int
	selected  int
	trigger   []rune
}

func (cl *commandline) construct(commands []string, width int) (omit, line int) {
	maxCount := (width + 1) / (cl.maxLength + 1)
	b := make([]byte, 0, 16)
	for i, c := range commands {
		if len(c) > width {
			omit++
			continue
		}
		if i == cl.selected-1 {
			b = append(b, "\033[7m"...)
		}
		b = append(b, c...)
		if i == cl.selected-1 {
			b = append(b, "\033[0m"...)
		}
		b = append(b, strings.Repeat(" ", cl.maxLength+1-len(c))...)
		if (i+1)%maxCount == 0 {
			line++
			b = append(b, '\n')
			cl.w.Write(b)
			b = b[:0]
		}
	}
	cl.w.Write(b)
	return omit, line
}

func (cl *commandline) refresh() {
	if cl.compl != nil && len(cl.compl) < 100 {
		width, _ := getWidth()
		cl.w.WriteString("\n\n")
		cl.w.WriteString("\r\033[J")
		_, line := cl.construct(cl.compl, int(width))
		fmt.Fprintf(cl.w, "\033[%vA", 2+line)
	} else {
		cl.w.WriteString("\r\033[J")
	}

	if cl.mode == insertMode {
		cl.w.WriteString("\033[B")
		cl.w.WriteString("\r\033[K")
		cl.w.WriteString("-- INSERT --")
		cl.w.WriteString("\033[A")
		cl.w.WriteString("\r\033[K")
	} else {
		cl.w.WriteString("\r\033[J")
	}

	cl.w.WriteString(prompt)
	cl.w.WriteString(string(cl.buf))
	cl.w.WriteString(fmt.Sprintf("\033[%vG", len(prompt)+runewidth.StringWidth(string(cl.buf[:cl.index]))+1))
	cl.w.Flush()
}

func (cl *commandline) moveBackward() {
	if cl.index == 0 {
		return
	}
	cl.index--
}

func (cl *commandline) moveForward() {
	if cl.index == len(cl.buf) {
		return
	}
	cl.index++
}

func (cl *commandline) appendChar(ch rune) {
	switch cl.index {
	case 0:
		cl.buf = append([]rune{ch}, cl.buf...)
	case len(cl.buf):
		cl.buf = append(cl.buf, ch)
	default:
		buf := make([]rune, cl.index, len(cl.buf)+1)
		copy(buf, cl.buf[:cl.index])
		buf = append(buf, ch)
		buf = append(buf, cl.buf[cl.index:]...)
		cl.buf = buf
	}
	cl.index++
}

func (cl *commandline) deleteChar() {
	switch cl.index {
	case 0:
		return
	case 1:
		cl.buf = cl.buf[1:]
	case len(cl.buf):
		cl.buf = cl.buf[:cl.index-1]
	default:
		cl.buf = append(cl.buf[:cl.index-1], cl.buf[cl.index:]...)
	}
	cl.index--
}

func (cl *commandline) delete(from, to int) {
	left := from
	right := to
	if from > to {
		left = to
		right = from
	}
	if left < 0 {
		left = 0
	}
	if right > len(cl.buf) {
		right = len(cl.buf)
	}
	switch {
	case left == 0:
		cl.buf = cl.buf[right:]
	case right == len(cl.buf):
		cl.buf = cl.buf[:left]
	default:
		cl.buf = append(cl.buf[:left], cl.buf[right:]...)
	}
	switch {
	case cl.index < left:
	case right < cl.index:
		cl.index = cl.index - (right - left)
	default:
		cl.index = left
	}
}

func (cl *commandline) operate(pending rune, from, to int) {
	switch pending {
	case 'c', 'd':
		cl.delete(from, to)
		if pending == 'c' {
			cl.mode = insertMode
			return
		}
	case 'y':
	}
	cl.mode = normalMode
}

func (cl *commandline) complete() {
	cl.selected = 0
	var maxLength int
	paths := strings.Split(os.Getenv("PATH"), ":")
	var compl []string
	for _, path := range paths {
		files, err := ioutil.ReadDir(path)
		if err != nil {
			return // err
		}
		for _, file := range files {
			if strings.HasPrefix(file.Name(), string(cl.buf[:cl.index])) {
				compl = append(compl, file.Name())
				if len(file.Name()) > maxLength {
					maxLength = len(file.Name())
				}
			}
		}
	}
	cl.compl = compl
	cl.maxLength = maxLength
	cl.trigger = cl.buf[:cl.index]
}

func (cl *commandline) insert(s []rune, at int) {
	switch at {
	case 0:
		cl.buf = append(s, cl.buf...)
	case len(cl.buf):
		cl.buf = append(cl.buf, s...)
	default:
		s = append(cl.buf[:at], s...)
		cl.buf = append(s, cl.buf[at:]...)
	}
	if at <= cl.index {
		cl.index += len(s)
	}
}

func (cl *commandline) move(to int) {
	switch {
	case to >= len(cl.buf):
		switch cl.mode {
		case insertMode:
			cl.index = len(cl.buf)
		default:
			cl.index = len(cl.buf) - 1
		}
	case to <= 0:
		cl.index = 0
	default:
		cl.index = to
	}
}

func (cl *commandline) completeMode(rd *Reader) error {
	defer func() { cl.compl = nil }()
	for {
		cl.refresh()
		ch, err := rd.Read()
		if err != nil {
			return err
		}
		switch ch {
		case CharCtrlM:
			return nil
		case CharCtrlN, CharCtrlI:
			if cl.selected != len(cl.compl) {
				cl.selected++
				cl.buf = []rune(cl.compl[cl.selected-1])
				cl.index = len(cl.buf)
			} else {
				cl.selected = 0
				cl.buf = cl.trigger
				cl.index = len(cl.buf)
			}
		case CharCtrlP:
			if cl.selected != 1 {
				cl.selected--
				cl.buf = []rune(cl.compl[cl.selected-1])
				cl.index = len(cl.buf)
			} else {
				cl.selected = len(cl.compl) + 1
				cl.buf = cl.trigger
				cl.index = len(cl.buf)
			}
		case ' ':
			cl.insert([]rune{' '}, cl.index)
			return nil
		case CharBackspace:
			cl.delete(cl.index, cl.index-1)
			return nil
		default:
			cl.insert([]rune{ch}, cl.index)
			return nil
		}
	}
}
<commit_msg>Reduce types for completion<commit_after>package main

// TODO: refactor

import (
	"bufio"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"strings"

	"github.com/elpinal/coco3/eval"
	"github.com/elpinal/coco3/parser"
	"github.com/mattn/go-runewidth"
)

var prompt = "; "

type history struct {
	lines [][]rune
	i     int
}

func main() {
	var command = flag.String("c", "", "take first argument as a command to execute")
	flag.Parse()
	if *command != "" {
		if err := execute([]byte(*command)); err != nil {
			fmt.Fprintln(os.Stderr, err)
		}
		return
	}
	var hist history
	for {
		if err := loop(&hist); err != nil {
			fmt.Fprintln(os.Stderr, err)
		}
	}
}

const (
	CharCtrlA = iota + 1
	CharCtrlB
	CharCtrlC
	CharCtrlD
	CharCtrlE
	CharCtrlF
	CharCtrlG
	CharCtrlH
	CharCtrlI
	CharCtrlJ
	CharCtrlK
	CharCtrlL
	CharCtrlM
	CharCtrlN
	CharCtrlO
	CharCtrlP
	CharCtrlQ
	CharCtrlR
	CharCtrlS
	CharCtrlT
	CharCtrlU
	CharCtrlV
	CharCtrlW
	CharCtrlX
	CharCtrlY
	CharCtrlZ
	CharEscape

	CharBackspace = 127
)

func loop(hist *history) error {
	fmt.Print("\r\033[J")
	fmt.Print("\n")
	fmt.Print("-- INSERT --")
	fmt.Print("\033[A")
	fmt.Print("\r")
	fmt.Print(prompt)

	rd := NewReader(os.Stdin)
	lines := make([][]rune, len(hist.lines))
	copy(lines, hist.lines)
	cl := &commandline{
		w: bufio.NewWriter(os.Stdout),
		hist: history{
			lines: lines,
			i:     hist.i,
		},
		mode: insertMode,
	}
	state, err := enterRowMode()
	if err != nil {
		return err
	}
LOOP:
	for {
		ch, err := rd.Read()
		if err != nil {
			return err
		}
		switch cl.mode {
		case normalMode:
			switch ch {
			case CharCtrlM:
				break LOOP
			case 'h':
				cl.toLeft()
			case 'l':
				cl.toRight()
			case '0':
				cl.toTheFirst()
			case '^':
				cl.toTheFirstNonBlank()
			case '$':
				cl.toTheEnd()
			case 'k':
				cl.prevHistory()
			case 'j':
				cl.nextHistory()
			case 'w':
				cl.wordForward()
			case 'W':
				cl.wordForwardNonBlank()
			case 'b':
				cl.wordBackward()
			case 'B':
				cl.wordBackwardNonBlank()
			case 'a':
				cl.moveForward()
				cl.mode = insertMode
			case 'i':
				cl.mode = insertMode
			case 'x':
				cl.deleteUnder()
			case 'c', 'd', 'y':
				cl.mode = operatorPendingMode
				cl.pending = ch
			case 'g':
				ch1, err := rd.Read()
				if err != nil {
					return err
				}
				switch ch1 {
				case '_':
					cl.toTheLastNonBlank()
				}
			default:
			}
		case insertMode:
			switch ch {
			case CharCtrlM:
				break LOOP
			case CharEscape:
				cl.moveBackward()
				cl.mode = normalMode
			case CharBackspace:
				cl.deleteChar()
			case CharCtrlI:
				cl.complete()
				if cl.compl != nil {
					err := cl.completeMode(rd)
					if err != nil {
						return err
					}
				}
			default:
				cl.appendChar(ch)
			}
		case operatorPendingMode:
			switch ch {
			case 'h':
				from := cl.index
				cl.toLeft()
				to := cl.index
				cl.operate(cl.pending, from, to)
			case 'l':
				from := cl.index
				cl.toRight()
				to := cl.index
				cl.operate(cl.pending, from, to)
			case cl.pending:
				from := 0
				to := len(cl.buf)
				cl.operate(cl.pending, from, to)
			default:
				cl.mode = normalMode
			}
		}
		cl.refresh()
	}
	cl.w.WriteByte('\n')
	cl.w.WriteString("\r\033[K")
	cl.w.Flush()
	err = exitRowMode(state)
	if err != nil {
		return err
	}
	if len(hist.lines) == 0 || string(hist.lines[hist.i-1]) != string(cl.buf) {
		hist.lines = append(hist.lines, cl.buf)
		hist.i++
	}
	return execute([]byte(string(cl.buf)))
}

func execute(b []byte) error {
	f, err := parser.ParseSrc(b)
	if err != nil {
		return err
	}
	return eval.Eval(f.Lines)
}

type commandline struct {
	w     *bufio.Writer
	buf   []rune
	index int

	hist history

	mode    mode
	pending rune

	compl     []string
	maxLength int
	selected  int
	trigger   []rune
}

func (cl *commandline) construct(commands []string, width int) (omit, line int) {
	maxCount := (width + 1) / (cl.maxLength + 1)
	b := make([]byte, 0, 16)
	for i, c := range commands {
		if len(c) > width {
			omit++
			continue
		}
		if i == cl.selected-1 {
			b = append(b, "\033[7m"...)
		}
		b = append(b, c...)
		if i == cl.selected-1 {
			b = append(b, "\033[0m"...)
		}
		b = append(b, strings.Repeat(" ", cl.maxLength+1-len(c))...)
		if (i+1)%maxCount == 0 {
			line++
			b = append(b, '\n')
			cl.w.Write(b)
			b = b[:0]
		}
	}
	cl.w.Write(b)
	return omit, line
}

func (cl *commandline) refresh() {
	if cl.compl != nil && len(cl.compl) < 100 {
		width, _ := getWidth()
		cl.w.WriteString("\n\n")
		cl.w.WriteString("\r\033[J")
		_, line := cl.construct(cl.compl, int(width))
		fmt.Fprintf(cl.w, "\033[%vA", 2+line)
	} else {
		cl.w.WriteString("\r\033[J")
	}

	if cl.mode == insertMode {
		cl.w.WriteString("\033[B")
		cl.w.WriteString("\r\033[K")
		cl.w.WriteString("-- INSERT --")
		cl.w.WriteString("\033[A")
		cl.w.WriteString("\r\033[K")
	} else {
		cl.w.WriteString("\r\033[J")
	}

	cl.w.WriteString(prompt)
	cl.w.WriteString(string(cl.buf))
	cl.w.WriteString(fmt.Sprintf("\033[%vG", len(prompt)+runewidth.StringWidth(string(cl.buf[:cl.index]))+1))
	cl.w.Flush()
}

func (cl *commandline) moveBackward() {
	if cl.index == 0 {
		return
	}
	cl.index--
}

func (cl *commandline) moveForward() {
	if cl.index == len(cl.buf) {
		return
	}
	cl.index++
}

func (cl *commandline) appendChar(ch rune) {
	switch cl.index {
	case 0:
		cl.buf = append([]rune{ch}, cl.buf...)
	case len(cl.buf):
		cl.buf = append(cl.buf, ch)
	default:
		buf := make([]rune, cl.index, len(cl.buf)+1)
		copy(buf, cl.buf[:cl.index])
		buf = append(buf, ch)
		buf = append(buf, cl.buf[cl.index:]...)
		cl.buf = buf
	}
	cl.index++
}

func (cl *commandline) deleteChar() {
	switch cl.index {
	case 0:
		return
	case 1:
		cl.buf = cl.buf[1:]
	case len(cl.buf):
		cl.buf = cl.buf[:cl.index-1]
	default:
		cl.buf = append(cl.buf[:cl.index-1], cl.buf[cl.index:]...)
	}
	cl.index--
}

func (cl *commandline) delete(from, to int) {
	left := from
	right := to
	if from > to {
		left = to
		right = from
	}
	if left < 0 {
		left = 0
	}
	if right > len(cl.buf) {
		right = len(cl.buf)
	}
	switch {
	case left == 0:
		cl.buf = cl.buf[right:]
	case right == len(cl.buf):
		cl.buf = cl.buf[:left]
	default:
		cl.buf = append(cl.buf[:left], cl.buf[right:]...)
	}
	switch {
	case cl.index < left:
	case right < cl.index:
		cl.index = cl.index - (right - left)
	default:
		cl.index = left
	}
}

func (cl *commandline) operate(pending rune, from, to int) {
	switch pending {
	case 'c', 'd':
		cl.delete(from, to)
		if pending == 'c' {
			cl.mode = insertMode
			return
		}
	case 'y':
	}
	cl.mode = normalMode
}

func (cl *commandline) complete() {
	cl.selected = 1
	var maxLength int
	paths := strings.Split(os.Getenv("PATH"), ":")
	var compl []string
	for _, path := range paths {
		files, err := ioutil.ReadDir(path)
		if err != nil {
			return // err
		}
		for _, file := range files {
			if strings.HasPrefix(file.Name(), string(cl.buf[:cl.index])) {
				compl = append(compl, file.Name())
				if len(file.Name()) > maxLength {
					maxLength = len(file.Name())
				}
			}
		}
	}
	cl.compl = compl
	cl.maxLength = maxLength
	cl.trigger = cl.buf[:cl.index]
}

func (cl *commandline) insert(s []rune, at int) {
	switch at {
	case 0:
		cl.buf = append(s, cl.buf...)
	case len(cl.buf):
		cl.buf = append(cl.buf, s...)
	default:
		s = append(cl.buf[:at], s...)
		cl.buf = append(s, cl.buf[at:]...)
	}
	if at <= cl.index {
		cl.index += len(s)
	}
}

func (cl *commandline) move(to int) {
	switch {
	case to >= len(cl.buf):
		switch cl.mode {
		case insertMode:
			cl.index = len(cl.buf)
		default:
			cl.index = len(cl.buf) - 1
		}
	case to <= 0:
		cl.index = 0
	default:
		cl.index = to
	}
}

func (cl *commandline) completeMode(rd *Reader) error {
	defer func() { cl.compl = nil }()
	cl.buf = []rune(cl.compl[cl.selected-1])
	cl.index = len(cl.buf)
	for {
		cl.refresh()
		ch, err := rd.Read()
		if err != nil {
			return err
		}
		switch ch {
		case CharCtrlM:
			return nil
		case CharCtrlN, CharCtrlI:
			if cl.selected != len(cl.compl) {
				cl.selected++
				cl.buf = []rune(cl.compl[cl.selected-1])
				cl.index = len(cl.buf)
			} else {
				cl.selected = 0
				cl.buf = cl.trigger
				cl.index = len(cl.buf)
			}
		case CharCtrlP:
			if cl.selected != 1 {
				cl.selected--
				cl.buf = []rune(cl.compl[cl.selected-1])
				cl.index = len(cl.buf)
			} else {
				cl.selected = len(cl.compl) + 1
				cl.buf = cl.trigger
				cl.index = len(cl.buf)
			}
		case ' ':
			cl.insert([]rune{' '}, cl.index)
			return nil
		case CharBackspace:
			cl.delete(cl.index, cl.index-1)
			return nil
		default:
			cl.insert([]rune{ch}, cl.index)
			return nil
		}
	}
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"fmt"
	"github.com/aquilax/go-dirble"
	"github.com/codegangsta/cli"
	"net/http"
	"os"
	"strconv"
)

const (
	appName    = "dirble-cli"
	appVersion = "0.0.1"
	defaultInt = -1
)

func getDirble(token string) *dirble.Dirble {
	tr := http.Transport{}
	return dirble.New(&tr, token)
}

func processResult(d interface{}, err error) {
	var res []byte
	if err != nil {
		panic(err)
	}
	if res, err = json.MarshalIndent(d, "", "	"); err != nil {
		panic(err)
	}
	fmt.Printf("%s\n", res)
}

func intToParam(c *cli.Context, name string) *int {
	if c.IsSet(name) {
		result := c.Int(name)
		return &result
	}
	return nil
}

func main() {
	app := cli.NewApp()
	app.Name = appName
	app.Version = appVersion
	app.Usage = "Fetches information from dirble.com"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "token, t",
			Value:  "",
			Usage:  "API Token",
			EnvVar: "DIRBLE_API_TOKEN",
		},
	}
	app.Commands = []cli.Command{
		{
			Name:    "stations",
			Aliases: []string{"st"},
			Usage:   "Get List of stations",
			Flags: []cli.Flag{
				cli.IntFlag{
					Name:  "page",
					Usage: "page to fetch",
				},
				cli.IntFlag{
					Name:  "ipp",
					Usage: "items per page",
				},
				cli.IntFlag{
					Name:  "offset",
					Usage: "offset",
				},
			},
			Action: func(c *cli.Context) {
				processResult(getDirble(c.GlobalString("token")).Stations(intToParam(c, "page"),
					intToParam(c, "ipp"), intToParam(c, "offset")))
			},
		}, {
			Name:  "country-stations",
			Usage: "Get List of stations for country",
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "all",
					Usage: "Get all stations",
				},
				cli.IntFlag{
					Name:  "page",
					Usage: "page to fetch",
				},
				cli.IntFlag{
					Name:  "ipp",
					Usage: "items per page",
				},
				cli.IntFlag{
					Name:  "offset",
					Usage: "offset",
				},
			},
			Action: func(c *cli.Context) {
				if len(c.Args()) > 0 {
					processResult(getDirble(c.GlobalString("token")).CountriesStations(c.Args()[0], c.Bool("all"),
						intToParam(c, "page"), intToParam(c, "ipp"), intToParam(c, "offset")))
				}
			},
		}, {
			Name:  "continents",
			Usage: "Get list of continents",
			Action: func(c *cli.Context) {
				processResult(getDirble(c.GlobalString("token")).Continents())
			},
		}, {
			Name:  "countries",
			Usage: "Get countries for continent",
			Action: func(c *cli.Context) {
				if len(c.Args()) > 0 {
					continentId, err := strconv.Atoi(c.Args()[0])
					if err != nil {
						panic(err)
					}
					processResult(getDirble(c.GlobalString("token")).ContinentsCountries(continentId))
				}
			},
		}, {
			Name:    "search",
			Aliases: []string{"s"},
			Usage:   "Search for station",
			Flags: []cli.Flag{
				cli.IntFlag{
					Name:  "page",
					Usage: "page to fetch",
				},
			},
			Action: func(c *cli.Context) {
				if len(c.Args()) > 0 {
					processResult(getDirble(c.GlobalString("token")).Search(c.Args()[0], intToParam(c, "page")))
				}
			},
		},
	}
	app.Run(os.Args)
}
<commit_msg>Countries<commit_after>package main

import (
	"encoding/json"
	"fmt"
	"github.com/aquilax/go-dirble"
	"github.com/codegangsta/cli"
	"net/http"
	"os"
	"strconv"
)

const (
	appName    = "dirble-cli"
	appVersion = "0.0.1"
	defaultInt = -1
)

func getDirble(token string) *dirble.Dirble {
	tr := http.Transport{}
	return dirble.New(&tr, token)
}

func processResult(d interface{}, err error) {
	var res []byte
	if err != nil {
		panic(err)
	}
	if res, err = json.MarshalIndent(d, "", "	"); err != nil {
		panic(err)
	}
	fmt.Printf("%s\n", res)
}

func intToParam(c *cli.Context, name string) *int {
	if c.IsSet(name) {
		result := c.Int(name)
		return &result
	}
	return nil
}

func main() {
	app := cli.NewApp()
	app.Name = appName
	app.Version = appVersion
	app.Usage = "Fetches information from dirble.com"
	app.Flags = []cli.Flag{
		cli.StringFlag{
			Name:   "token, t",
			Value:  "",
			Usage:  "API Token",
			EnvVar: "DIRBLE_API_TOKEN",
		},
	}
	app.Commands = []cli.Command{
		{
			Name:    "stations",
			Aliases: []string{"st"},
			Usage:   "Get List of stations",
			Flags: []cli.Flag{
				cli.IntFlag{
					Name:  "page",
					Usage: "page to fetch",
				},
				cli.IntFlag{
					Name:  "ipp",
					Usage: "items per page",
				},
				cli.IntFlag{
					Name:  "offset",
					Usage: "offset",
				},
			},
			Action: func(c *cli.Context) {
				processResult(getDirble(c.GlobalString("token")).Stations(intToParam(c, "page"),
					intToParam(c, "ipp"), intToParam(c, "offset")))
			},
		}, {
			Name:  "countries",
			Usage: "Get list of countries",
			Action: func(c *cli.Context) {
				processResult(getDirble(c.GlobalString("token")).Countries())
			},
		}, {
			Name:  "country-stations",
			Usage: "Get List of stations for country",
			Flags: []cli.Flag{
				cli.BoolFlag{
					Name:  "all",
					Usage: "Get all stations",
				},
				cli.IntFlag{
					Name:  "page",
					Usage: "page to fetch",
				},
				cli.IntFlag{
					Name:  "ipp",
					Usage: "items per page",
				},
				cli.IntFlag{
					Name:  "offset",
					Usage: "offset",
				},
			},
			Action: func(c *cli.Context) {
				if len(c.Args()) > 0 {
					processResult(getDirble(c.GlobalString("token")).CountriesStations(c.Args()[0], c.Bool("all"),
						intToParam(c, "page"), intToParam(c, "ipp"), intToParam(c, "offset")))
				}
			},
		}, {
			Name:  "continents",
			Usage: "Get list of continents",
			Action: func(c *cli.Context) {
				processResult(getDirble(c.GlobalString("token")).Continents())
			},
		}, {
			Name:  "countries",
			Usage: "Get countries for continent",
			Action: func(c *cli.Context) {
				if len(c.Args()) > 0 {
					continentId, err := strconv.Atoi(c.Args()[0])
					if err != nil {
						panic(err)
					}
					processResult(getDirble(c.GlobalString("token")).ContinentsCountries(continentId))
				}
			},
		}, {
			Name:    "search",
			Aliases: []string{"s"},
			Usage:   "Search for station",
			Flags: []cli.Flag{
				cli.IntFlag{
					Name:  "page",
					Usage: "page to fetch",
				},
			},
			Action: func(c *cli.Context) {
				if len(c.Args()) > 0 {
					processResult(getDirble(c.GlobalString("token")).Search(c.Args()[0], intToParam(c, "page")))
				}
			},
		},
	}
	app.Run(os.Args)
}
<|endoftext|>


<commit_before>package main

import (
	"honnef.co/go/importer"

	"code.google.com/p/go.tools/go/types"
	"github.com/kisielk/gotool"

	"flag"
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/token"
	"os"
	"path/filepath"
	"strings"
)

var (
	interfacesFrom string
	typesFrom      string
	reverse        bool
	printHelp      bool
)

func init() {
	flag.StringVar(&interfacesFrom, "interfaces", "std", "Comma-separated list of which packages to scan for interfaces. Defaults to std.")
	flag.StringVar(&typesFrom, "types", "", "Comma-separated list of packages whose types to check for implemented interfaces. Required.")
	flag.BoolVar(&reverse, "reverse", false, "Print 'implemented by' as opposed to 'implements' relations.")
	flag.BoolVar(&printHelp, "help", false, "Print a help text and exit.")

	flag.Parse()
}

type Interface struct {
	Name       string
	Underlying *types.Interface
	Obj        types.Object
}

type Type struct {
	Object   types.Object
	TypeName *types.TypeName
	Pointer  *types.Pointer
}

// getInterfaces extracts all the interfaces from the objects we
// parsed.
func getInterfaces(typs []Type) []Interface {
	var interfaces []Interface

	for _, typ := range typs {
		// Only types, not variables/constants
		// Only interfaces
		if iface, ok := typ.TypeName.Type().Underlying().(*types.Interface); ok {
			interfaces = append(interfaces, Interface{typ.Object.Name(), iface, typ.Object})
		}
	}

	return interfaces
}

func parseFile(fset *token.FileSet, fileName string) (f *ast.File, err error) {
	astFile, err := parser.ParseFile(fset, fileName, nil, 0)
	if err != nil {
		return f, fmt.Errorf("could not parse: %s", err)
	}

	return astFile, nil
}

type Context struct {
	allImports map[string]*types.Package
	context    types.Context
}

func NewContext() *Context {
	importer := importer.NewImporter()
	ctx := &Context{
		allImports: importer.Imports,
		context: types.Context{
			Import: importer.Import,
		},
	}

	return ctx
}

func (ctx *Context) getTypes(paths ...string) ([]Type, []error) {
	var errors []error
	var typs []Type

pathLoop:
	for _, path := range paths {
		buildPkg, err := build.Import(path, ".", 0)
		if err != nil {
			errors = append(errors, fmt.Errorf("Couldn't import %s: %s", path, err))
			continue
		}
		fset := token.NewFileSet()
		var astFiles []*ast.File
		var pkg *types.Package
		if buildPkg.Goroot {
			// TODO what if the compiled package in GoRoot is
			// outdated?
			pkg, err = types.GcImport(ctx.allImports, path)
			if err != nil {
				errors = append(errors, fmt.Errorf("Couldn't import %s: %s", path, err))
				continue
			}
		} else {
			if len(buildPkg.GoFiles) == 0 {
				errors = append(errors, fmt.Errorf("Couldn't parse %s: No (non cgo) Go files", path))
				continue pathLoop
			}
			for _, file := range buildPkg.GoFiles {
				astFile, err := parseFile(fset, filepath.Join(buildPkg.Dir, file))
				if err != nil {
					errors = append(errors, fmt.Errorf("Couldn't parse %s: %s", err))
					continue pathLoop
				}
				astFiles = append(astFiles, astFile)
			}

			pkg, err = check(ctx, astFiles[0].Name.Name, fset, astFiles)
			if err != nil {
				errors = append(errors, fmt.Errorf("Couldn't parse %s: %s\n", path, err))
				continue pathLoop
			}
		}

		scope := pkg.Scope()
		for i := 0; i < scope.NumEntries(); i++ {
			obj := scope.At(i)

			// Only types, not variables/constants
			if typ, ok := obj.(*types.TypeName); ok {
				typs = append(typs, Type{
					Object:   obj,
					TypeName: typ,
					Pointer:  types.NewPointer(typ.Type()),
				})
			}

		}
	}
	return typs, errors
}

func check(ctx *Context, name string, fset *token.FileSet, astFiles []*ast.File) (pkg *types.Package, err error) {
	return ctx.context.Check(name, fset, astFiles, nil)
}

func listErrors(errors []error) {
	for _, err := range errors {
		fmt.Println(err)
	}
}

func doesImplement(typ types.Type, iface *types.Interface) bool {
	fnc, _ := types.MissingMethod(typ, iface)
	return fnc == nil
}

func listImplementedInterfaces(universe, toCheck []Type) {
	interfaces := getInterfaces(universe)

	for _, typ := range toCheck {
		var implements []Interface
		var implementsPointer []Interface
		for _, iface := range interfaces {
			if iface.Underlying.NumMethods() == 0 {
				// Everything implements empty interfaces, skip those
				continue
			}

			if typ.Object.Pkg() == iface.Obj.Pkg() && typ.Object.Name() == iface.Name {
				// An interface will always implement itself, so skip those
				continue
			}

			if doesImplement(typ.Object.Type(), iface.Underlying) {
				implements = append(implements, iface)
			}

			if _, ok := typ.TypeName.Type().Underlying().(*types.Interface); !ok {
				if doesImplement(typ.Pointer.Underlying(), iface.Underlying) {
					implementsPointer = append(implementsPointer, iface)
				}
			}
		}

		if len(implements) > 0 {
			fmt.Printf("%s.%s implements...\n", typ.TypeName.Pkg().Path(), typ.Object.Name())
			for _, iface := range implements {
				fmt.Printf("\t%s.%s\n", iface.Obj.Pkg().Path(), iface.Name)
			}
		}
		// TODO DRY
		if len(implementsPointer) > 0 {
			fmt.Printf("*%s.%s implements...\n", typ.TypeName.Pkg().Path(), typ.Object.Name())
			for _, iface := range implementsPointer {
				fmt.Printf("\t%s.%s\n", iface.Obj.Pkg().Path(), iface.Name)
			}
		}
	}
}

func listImplementers(universe, toCheck []Type) {
	interfaces := getInterfaces(universe)

	for _, iface := range interfaces {
		var implementedBy []string
		for _, typ := range toCheck {
			if iface.Underlying.NumMethods() == 0 {
				// Everything implements empty interfaces, skip those
				continue
			}

			if typ.Object.Pkg() == iface.Obj.Pkg() && typ.Object.Name() == iface.Name {
				// An interface will always implement itself, so skip those
				continue
			}

			if doesImplement(typ.Object.Type(), iface.Underlying) {
				implementedBy = append(implementedBy, fmt.Sprintf("%s.%s", typ.TypeName.Pkg().Path(), typ.Object.Name()))
			}

			if _, ok := typ.TypeName.Type().Underlying().(*types.Interface); !ok {
				if doesImplement(typ.Pointer.Underlying(), iface.Underlying) {
					implementedBy = append(implementedBy, fmt.Sprintf("*%s.%s", typ.TypeName.Pkg().Path(), typ.Object.Name()))
				}
			}
		}

		if len(implementedBy) > 0 {
			fmt.Printf("%s.%s is implemented by...\n", iface.Obj.Pkg().Path(), iface.Name)
			for _, s := range implementedBy {
				fmt.Printf("\t%s\n", s)
			}
		}
	}
}

func main() {
	if printHelp {
		flag.Usage()
		fmt.Fprintln(os.Stderr)
		fmt.Fprintln(os.Stderr,
			`implements is a tool that will tell you which types implement which
interfaces, or alternatively by which types interfaces are
implemented.

You use it by specifying a set of packages to scan for interfaces and
another set of packages to scan for types. The two sets can but don't
have to overlap.

When specifying packages, "std" will stand for all of the standard
library. Also, the "..." pattern as understood by the go tool is
supported as well.

By default, implements will iterate all types and list the interfaces
they implement. By supplying the -reverse flag, however, it will
iterate all interfaces and list the types that implement the
interfaces.

Example: For all interfaces in the fmt package you want to know the
types in the standard library that implement them:

    implements -interfaces fmt -types std -reverse

Another example: For all types in your own package you want to know
which interfaces from the standard library they implement:

    implements -interfaces std -types my/own/package`)

		os.Exit(0)
	}

	if typesFrom == "" {
		flag.Usage()
		os.Exit(1)
	}

	ctx := NewContext()
	universe, errs := ctx.getTypes(gotool.ImportPaths(strings.Split(interfacesFrom, ","))...)
	listErrors(errs)
	toCheck, errs := ctx.getTypes(gotool.ImportPaths(strings.Split(typesFrom, ","))...)
	listErrors(errs)

	if reverse {
		listImplementers(universe, toCheck)
	} else {
		listImplementedInterfaces(universe, toCheck)
	}
}
<commit_msg>more upstream API changes<commit_after>package main

import (
	"honnef.co/go/importer"

	"code.google.com/p/go.tools/go/types"
	"github.com/kisielk/gotool"

	"flag"
	"fmt"
	"go/ast"
	"go/build"
	"go/parser"
	"go/token"
	"os"
	"path/filepath"
	"strings"
)

var (
	interfacesFrom string
	typesFrom      string
	reverse        bool
	printHelp      bool
)

func init() {
	flag.StringVar(&interfacesFrom, "interfaces", "std", "Comma-separated list of which packages to scan for interfaces. Defaults to std.")
	flag.StringVar(&typesFrom, "types", "", "Comma-separated list of packages whose types to check for implemented interfaces. Required.")
	flag.BoolVar(&reverse, "reverse", false, "Print 'implemented by' as opposed to 'implements' relations.")
	flag.BoolVar(&printHelp, "help", false, "Print a help text and exit.")

	flag.Parse()
}

type Interface struct {
	Name       string
	Underlying *types.Interface
	Obj        types.Object
}

type Type struct {
	Object   types.Object
	TypeName *types.TypeName
	Pointer  *types.Pointer
}

// getInterfaces extracts all the interfaces from the objects we
// parsed.
func getInterfaces(typs []Type) []Interface {
	var interfaces []Interface

	for _, typ := range typs {
		// Only types, not variables/constants
		// Only interfaces
		if iface, ok := typ.TypeName.Type().Underlying().(*types.Interface); ok {
			interfaces = append(interfaces, Interface{typ.Object.Name(), iface, typ.Object})
		}
	}

	return interfaces
}

func parseFile(fset *token.FileSet, fileName string) (f *ast.File, err error) {
	astFile, err := parser.ParseFile(fset, fileName, nil, 0)
	if err != nil {
		return f, fmt.Errorf("could not parse: %s", err)
	}

	return astFile, nil
}

type Context struct {
	allImports map[string]*types.Package
	context    types.Config
}

func NewContext() *Context {
	importer := importer.NewImporter()
	ctx := &Context{
		allImports: importer.Imports,
		context: types.Config{
			Import: importer.Import,
		},
	}

	return ctx
}

func (ctx *Context) getTypes(paths ...string) ([]Type, []error) {
	var errors []error
	var typs []Type

pathLoop:
	for _, path := range paths {
		buildPkg, err := build.Import(path, ".", 0)
		if err != nil {
			errors = append(errors, fmt.Errorf("Couldn't import %s: %s", path, err))
			continue
		}
		fset := token.NewFileSet()
		var astFiles []*ast.File
		var pkg *types.Package
		if buildPkg.Goroot {
			// TODO what if the compiled package in GoRoot is
			// outdated?
			pkg, err = types.GcImport(ctx.allImports, path)
			if err != nil {
				errors = append(errors, fmt.Errorf("Couldn't import %s: %s", path, err))
				continue
			}
		} else {
			if len(buildPkg.GoFiles) == 0 {
				errors = append(errors, fmt.Errorf("Couldn't parse %s: No (non cgo) Go files", path))
				continue pathLoop
			}
			for _, file := range buildPkg.GoFiles {
				astFile, err := parseFile(fset, filepath.Join(buildPkg.Dir, file))
				if err != nil {
					errors = append(errors, fmt.Errorf("Couldn't parse %s: %s", err))
					continue pathLoop
				}
				astFiles = append(astFiles, astFile)
			}

			pkg, err = check(ctx, astFiles[0].Name.Name, fset, astFiles)
			if err != nil {
				errors = append(errors, fmt.Errorf("Couldn't parse %s: %s\n", path, err))
				continue pathLoop
			}
		}

		scope := pkg.Scope()
		for i := 0; i < scope.NumEntries(); i++ {
			obj := scope.At(i)

			// Only types, not variables/constants
			if typ, ok := obj.(*types.TypeName); ok {
				typs = append(typs, Type{
					Object:   obj,
					TypeName: typ,
					Pointer:  types.NewPointer(typ.Type()),
				})
			}

		}
	}
	return typs, errors
}

func check(ctx *Context, name string, fset *token.FileSet, astFiles []*ast.File) (pkg *types.Package, err error) {
	return ctx.context.Check(name, fset, astFiles, nil)
}

func listErrors(errors []error) {
	for _, err := range errors {
		fmt.Println(err)
	}
}

func doesImplement(typ types.Type, iface *types.Interface) bool {
	fnc, _ := types.MissingMethod(typ, iface)
	return fnc == nil
}

func listImplementedInterfaces(universe, toCheck []Type) {
	interfaces := getInterfaces(universe)

	for _, typ := range toCheck {
		var implements []Interface
		var implementsPointer []Interface
		for _, iface := range interfaces {
			if iface.Underlying.NumMethods() == 0 {
				// Everything implements empty interfaces, skip those
				continue
			}

			if typ.Object.Pkg() == iface.Obj.Pkg() && typ.Object.Name() == iface.Name {
				// An interface will always implement itself, so skip those
				continue
			}

			if doesImplement(typ.Object.Type(), iface.Underlying) {
				implements = append(implements, iface)
			}

			if _, ok := typ.TypeName.Type().Underlying().(*types.Interface); !ok {
				if doesImplement(typ.Pointer.Underlying(), iface.Underlying) {
					implementsPointer = append(implementsPointer, iface)
				}
			}
		}

		if len(implements) > 0 {
			fmt.Printf("%s.%s implements...\n", typ.TypeName.Pkg().Path(), typ.Object.Name())
			for _, iface := range implements {
				fmt.Printf("\t%s.%s\n", iface.Obj.Pkg().Path(), iface.Name)
			}
		}
		// TODO DRY
		if len(implementsPointer) > 0 {
			fmt.Printf("*%s.%s implements...\n", typ.TypeName.Pkg().Path(), typ.Object.Name())
			for _, iface := range implementsPointer {
				fmt.Printf("\t%s.%s\n", iface.Obj.Pkg().Path(), iface.Name)
			}
		}
	}
}

func listImplementers(universe, toCheck []Type) {
	interfaces := getInterfaces(universe)

	for _, iface := range interfaces {
		var implementedBy []string
		for _, typ := range toCheck {
			if iface.Underlying.NumMethods() == 0 {
				// Everything implements empty interfaces, skip those
				continue
			}

			if typ.Object.Pkg() == iface.Obj.Pkg() && typ.Object.Name() == iface.Name {
				// An interface will always implement itself, so skip those
				continue
			}

			if doesImplement(typ.Object.Type(), iface.Underlying) {
				implementedBy = append(implementedBy, fmt.Sprintf("%s.%s", typ.TypeName.Pkg().Path(), typ.Object.Name()))
			}

			if _, ok := typ.TypeName.Type().Underlying().(*types.Interface); !ok {
				if doesImplement(typ.Pointer.Underlying(), iface.Underlying) {
					implementedBy = append(implementedBy, fmt.Sprintf("*%s.%s", typ.TypeName.Pkg().Path(), typ.Object.Name()))
				}
			}
		}

		if len(implementedBy) > 0 {
			fmt.Printf("%s.%s is implemented by...\n", iface.Obj.Pkg().Path(), iface.Name)
			for _, s := range implementedBy {
				fmt.Printf("\t%s\n", s)
			}
		}
	}
}

func main() {
	if printHelp {
		flag.Usage()
		fmt.Fprintln(os.Stderr)
		fmt.Fprintln(os.Stderr,
			`implements is a tool that will tell you which types implement which
interfaces, or alternatively by which types interfaces are
implemented.

You use it by specifying a set of packages to scan for interfaces and
another set of packages to scan for types. The two sets can but don't
have to overlap.

When specifying packages, "std" will stand for all of the standard
library. Also, the "..." pattern as understood by the go tool is
supported as well.

By default, implements will iterate all types and list the interfaces
they implement. By supplying the -reverse flag, however, it will
iterate all interfaces and list the types that implement the
interfaces.

Example: For all interfaces in the fmt package you want to know the
types in the standard library that implement them:

    implements -interfaces fmt -types std -reverse

Another example: For all types in your own package you want to know
which interfaces from the standard library they implement:

    implements -interfaces std -types my/own/package`)

		os.Exit(0)
	}

	if typesFrom == "" {
		flag.Usage()
		os.Exit(1)
	}

	ctx := NewContext()
	universe, errs := ctx.getTypes(gotool.ImportPaths(strings.Split(interfacesFrom, ","))...)
	listErrors(errs)
	toCheck, errs := ctx.getTypes(gotool.ImportPaths(strings.Split(typesFrom, ","))...)
	listErrors(errs)

	if reverse {
		listImplementers(universe, toCheck)
	} else {
		listImplementedInterfaces(universe, toCheck)
	}
}
<|endoftext|>


<commit_before>// dither project main.go
package main

import (
	"flag"
	"fmt"
	"image"
	"log"
	"math"
	"os"
	"sync"

	"math/rand"

	_ "image/gif"
	_ "image/jpeg"
	_ "image/png"

	"image/color"

	"github.com/nfnt/resize"
	"golang.org/x/image/tiff"
)

var (
	xBlocks       int
	yBlocks       int
	seed          int64
	smooth        bool
	rescaleOutput bool
	gamma         float64
	colorDither   bool
)

const A = 0.985

func main() {
	flag.IntVar(&xBlocks, "x", 0, "Blocks on horizontal side.")
	flag.IntVar(&yBlocks, "y", 0, "Blocks on vertical side.")
	flag.Int64Var(&seed, "r", 0, "Random number seed for dithering.")
	flag.BoolVar(&smooth, "s", false, "Produce smoother look.")
	flag.BoolVar(&rescaleOutput, "o", false, "Output image is one pixel per block.")
	flag.Float64Var(&gamma, "g", 0.0, "Gamma of input image. If 0.0, then assume sRGB.")
	flag.BoolVar(&colorDither, "c", false, "Dither in color.")
	flag.Parse()
	gammaInit()

	await := &sync.WaitGroup{}
	for _, fname := range flag.Args() {
		await.Add(1)
		go func(filename string) {
			defer await.Done()
			dithered := ditherImage(imgFromFName(filename))
			save(dithered, filename)
		}(fname)
	}
	await.Wait()
}

func imgFromFName(fname string) image.Image {
	f, err := os.Open(fname)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	img, _, err := image.Decode(f)
	if err != nil {
		log.Fatal(err)
	}

	return transcode(img, decodeLUT)
}

func save(i image.Image, name string) {
	var typeName string
	if smooth {
		typeName = "s"
	} else {
		typeName = "d"
	}

	var (
		sizeX int
		sizeY int
	)

	switch {
	case xBlocks != 0 && yBlocks != 0:
		sizeX = xBlocks
		sizeY = yBlocks

	case xBlocks == 0 && yBlocks != 0:
		sizeX = yBlocks * i.Bounds().Size().X / i.Bounds().Size().Y
		sizeY = yBlocks

	case xBlocks != 0 && yBlocks == 0:
		sizeX = xBlocks
		sizeY = xBlocks * i.Bounds().Size().Y / i.Bounds().Size().X

	default:
		sizeX = i.Bounds().Size().X
		sizeY = i.Bounds().Size().Y
	}

	w, err := os.Create(fmt.Sprintf("%s.%s%04dx%04d.tiff", name, typeName, sizeX, sizeY))
	if err != nil {
		log.Fatal(err)
	}
	defer w.Close()

	out := transcode(i, encodeLUT)
	err = tiff.Encode(w, out, &tiff.Options{Compression: tiff.Deflate, Predictor: true})
	if err != nil {
		log.Fatal(err)
	}
}

var white = color.Gray16{Y: 65535}
var black = color.Gray16{Y: 0}

func ditherImage(i image.Image) image.Image {
	if xBlocks == 0 && yBlocks == 0 {
		return ditherImage1to1(i)
	}

	smaller := resize.Resize(uint(xBlocks), uint(yBlocks), i, resize.Lanczos3)
	dith := ditherImage1to1(smaller)
	finalWidth := uint(i.Bounds().Size().X)
	finalHeight := uint(i.Bounds().Size().Y)
	if smooth {
		return resize.Resize(finalWidth, finalHeight, dith, resize.Bicubic)
	} else {
		if rescaleOutput {
			return dith
		} else {
			return resize.Resize(finalWidth, finalHeight, dith, resize.NearestNeighbor)
		}
	}
}

func ditherImage1to1(i image.Image) image.Image {
	if colorDither {
		return ditherImage1to1Color(i)
	}

	b := i.Bounds()
	d := image.NewGray16(b)
	r := rand.New(rand.NewSource(seed))

	for y := b.Min.Y; y < b.Max.Y; y += 1 {
		for x := b.Min.X; x < b.Max.X; x += 1 {
			value := color.Gray16Model.Convert(i.At(x, y)).(color.Gray16)
			randVal := uint16(r.Uint32())
			if randVal < value.Y {
				d.Set(x, y, white)
			} else {
				d.Set(x, y, black)
			}
		}
	}

	return d
}

func ditherImage1to1Color(i image.Image) image.Image {
	b := i.Bounds()
	d := image.NewRGBA64(b)
	r := rand.New(rand.NewSource(seed))

	for y := b.Min.Y; y < b.Max.Y; y += 1 {
		for x := b.Min.X; x < b.Max.X; x += 1 {
			rval, gval, bval, aval := i.At(x, y).RGBA()
			if uint16(r.Uint32()) < uint16(rval) {
				rval = 65535
			} else {
				rval = 0
			}
			if uint16(r.Uint32()) < uint16(gval) {
				gval = 65535
			} else {
				gval = 0
			}
			if uint16(r.Uint32()) < uint16(bval) {
				bval = 65535
			} else {
				bval = 0
			}
			d.SetRGBA64(x, y, color.RGBA64{
				uint16(rval),
				uint16(gval),
				uint16(bval),
				uint16(aval),
			})
		}
	}

	return d
}

func gammaDecode(in float64) float64 {
	return A * math.Pow(in, gamma)
}

const (
	a  = 0.055
	a1 = a + 1.0
	e  = 1.0 / 2.4
)

func sRGBDecode(in float64) float64 {
	if in <= 0.04045 {
		return in / 12.92
	}
	return math.Pow((in+a)/a1, 2.4)
}

func sRGBEncode(in float64) float64 {
	if in <= 0.0031308 {
		return in * 12.92
	}
	return a1*math.Pow(in, e) - a
}

var (
	decodeLUT []uint16
	encodeLUT []uint16
)

func gammaInit() {
	decodeLUT = make([]uint16, 65536)
	if gamma == 0.0 {
		for i := 0; i < 65536; i++ {
			decodeLUT[i] = uint16(sRGBDecode(float64(i)/65536.0) * 65536.0)
		}
	} else {
		for i := 0; i < 65536; i++ {
			decodeLUT[i] = uint16(gammaDecode(float64(i)/65536.0) * 65536.0)
		}
	}
	encodeLUT = make([]uint16, 65536)
	for i := 0; i < 65536; i++ {
		encodeLUT[i] = uint16(sRGBEncode(float64(i)/65536.0) * 65536.0)
	}
}

func transcode(in image.Image, lut []uint16) image.Image {
	b := in.Bounds()
	out := image.NewRGBA64(b)

	for y := b.Min.Y; y < b.Max.Y; y += 1 {
		for x := b.Min.X; x < b.Max.X; x += 1 {
			rval, gval, bval, aval := in.At(x, y).RGBA()
			out.SetRGBA64(x, y, color.RGBA64{
				lut[rval],
				lut[gval],
				lut[bval],
				lut[aval],
			})
		}
	}

	return out
}
<commit_msg>Add, but don't call, blur functions<commit_after>// dither project main.go
package main

import (
	"flag"
	"fmt"
	"image"
	"image/color"
	_ "image/gif"
	_ "image/jpeg"
	_ "image/png"
	"log"
	"math"
	"math/rand"
	"os"
	"sync"

	"github.com/nfnt/resize"
	"golang.org/x/image/tiff"
)

var (
	xBlocks       int
	yBlocks       int
	seed          int64
	smooth        bool
	rescaleOutput bool
	gamma         float64
	colorDither   bool
)

const A = 0.985

func main() {
	flag.IntVar(&xBlocks, "x", 0, "Blocks on horizontal side.")
	flag.IntVar(&yBlocks, "y", 0, "Blocks on vertical side.")
	flag.Int64Var(&seed, "r", 0, "Random number seed for dithering.")
	flag.BoolVar(&smooth, "s", false, "Produce smoother look.")
	flag.BoolVar(&rescaleOutput, "o", false, "Output image is one pixel per block.")
	flag.Float64Var(&gamma, "g", 0.0, "Gamma of input image. If 0.0, then assume sRGB.")
	flag.BoolVar(&colorDither, "c", false, "Dither in color.")
	flag.Parse()
	gammaInit()

	await := &sync.WaitGroup{}
	for _, fname := range flag.Args() {
		await.Add(1)
		go func(filename string) {
			defer await.Done()
			dithered := ditherImage(imgFromFName(filename))
			save(dithered, filename)
		}(fname)
	}
	await.Wait()
}

func imgFromFName(fname string) image.Image {
	f, err := os.Open(fname)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	img, _, err := image.Decode(f)
	if err != nil {
		log.Fatal(err)
	}

	return transcode(img, decodeLUT)
}

func save(i image.Image, name string) {
	var typeName string
	if smooth {
		typeName = "s"
	} else {
		typeName = "d"
	}

	var (
		sizeX int
		sizeY int
	)

	switch {
	case xBlocks != 0 && yBlocks != 0:
		sizeX = xBlocks
		sizeY = yBlocks

	case xBlocks == 0 && yBlocks != 0:
		sizeX = yBlocks * i.Bounds().Size().X / i.Bounds().Size().Y
		sizeY = yBlocks

	case xBlocks != 0 && yBlocks == 0:
		sizeX = xBlocks
		sizeY = xBlocks * i.Bounds().Size().Y / i.Bounds().Size().X

	default:
		sizeX = i.Bounds().Size().X
		sizeY = i.Bounds().Size().Y
	}

	w, err := os.Create(fmt.Sprintf("%s.%s%04dx%04d.tiff", name, typeName, sizeX, sizeY))
	if err != nil {
		log.Fatal(err)
	}
	defer w.Close()

	out := transcode(i, encodeLUT)
	err = tiff.Encode(w, out, &tiff.Options{Compression: tiff.Deflate, Predictor: true})
	if err != nil {
		log.Fatal(err)
	}
}

var white = color.Gray16{Y: 65535}
var black = color.Gray16{Y: 0}

func ditherImage(i image.Image) image.Image {
	if xBlocks == 0 && yBlocks == 0 {
		return ditherImage1to1(i)
	}

	smaller := resize.Resize(uint(xBlocks), uint(yBlocks), i, resize.Lanczos3)
	dith := ditherImage1to1(smaller)
	finalWidth := uint(i.Bounds().Size().X)
	finalHeight := uint(i.Bounds().Size().Y)
	if smooth {
		return resize.Resize(finalWidth, finalHeight, dith, resize.Bicubic)
	} else {
		if rescaleOutput {
			return dith
		} else {
			return resize.Resize(finalWidth, finalHeight, dith, resize.NearestNeighbor)
		}
	}
}

func ditherImage1to1(i image.Image) image.Image {
	if colorDither {
		return ditherImage1to1Color(i)
	}

	b := i.Bounds()
	d := image.NewGray16(b)
	r := rand.New(rand.NewSource(seed))

	for y := b.Min.Y; y < b.Max.Y; y += 1 {
		for x := b.Min.X; x < b.Max.X; x += 1 {
			value := color.Gray16Model.Convert(i.At(x, y)).(color.Gray16)
			randVal := uint16(r.Uint32())
			if randVal < value.Y {
				d.Set(x, y, white)
			} else {
				d.Set(x, y, black)
			}
		}
	}

	return d
}

func ditherImage1to1Color(i image.Image) image.Image {
	b := i.Bounds()
	d := image.NewRGBA64(b)
	r := rand.New(rand.NewSource(seed))

	for y := b.Min.Y; y < b.Max.Y; y += 1 {
		for x := b.Min.X; x < b.Max.X; x += 1 {
			rval, gval, bval, aval := i.At(x, y).RGBA()
			if uint16(r.Uint32()) < uint16(rval) {
				rval = 65535
			} else {
				rval = 0
			}
			if uint16(r.Uint32()) < uint16(gval) {
				gval = 65535
			} else {
				gval = 0
			}
			if uint16(r.Uint32()) < uint16(bval) {
				bval = 65535
			} else {
				bval = 0
			}
			d.SetRGBA64(x, y, color.RGBA64{
				uint16(rval),
				uint16(gval),
				uint16(bval),
				uint16(aval),
			})
		}
	}

	return d
}

func gammaDecode(in float64) float64 {
	return A * math.Pow(in, gamma)
}

const (
	a  = 0.055
	a1 = a + 1.0
	e  = 1.0 / 2.4
)

func sRGBDecode(in float64) float64 {
	if in <= 0.04045 {
		return in / 12.92
	}
	return math.Pow((in+a)/a1, 2.4)
}

func sRGBEncode(in float64) float64 {
	if in <= 0.0031308 {
		return in * 12.92
	}
	return a1*math.Pow(in, e) - a
}

var (
	decodeLUT []uint16
	encodeLUT []uint16
)

func gammaInit() {
	decodeLUT = make([]uint16, 65536)
	if gamma == 0.0 {
		for i := 0; i < 65536; i++ {
			decodeLUT[i] = uint16(sRGBDecode(float64(i)/65536.0) * 65536.0)
		}
	} else {
		for i := 0; i < 65536; i++ {
			decodeLUT[i] = uint16(gammaDecode(float64(i)/65536.0) * 65536.0)
		}
	}
	encodeLUT = make([]uint16, 65536)
	for i := 0; i < 65536; i++ {
		encodeLUT[i] = uint16(sRGBEncode(float64(i)/65536.0) * 65536.0)
	}
}

func transcode(in image.Image, lut []uint16) image.Image {
	b := in.Bounds()
	out := image.NewRGBA64(b)

	for y := b.Min.Y; y < b.Max.Y; y += 1 {
		for x := b.Min.X; x < b.Max.X; x += 1 {
			rval, gval, bval, aval := in.At(x, y).RGBA()
			out.SetRGBA64(x, y, color.RGBA64{
				lut[rval],
				lut[gval],
				lut[bval],
				lut[aval],
			})
		}
	}

	return out
}

// See http://blog.ivank.net/fastest-gaussian-blur.html
func gaussianBlur(in image.Image, radius float64) image.Image {
	bxs := boxesForGauss(radius, 3)

	out := image.NewRGBA64(in.Bounds())
	iter1 := image.NewRGBA64(in.Bounds())
	iter2 := image.NewRGBA64(in.Bounds())

	boxBlur(in, iter1, (bxs[0]-1)/2)
	boxBlur(iter1, iter2, (bxs[1]-1)/2)
	boxBlur(iter2, out, (bxs[2]-1)/2)

	return out
}

func boxBlur(in image.Image, out *image.RGBA64, r int) {
	tmp := image.NewRGBA64(in.Bounds())
	boxBlurHorizontal(in, tmp, r)
	boxBlurTotal(tmp, out, r)
}

func boxBlurHorizontal(in image.Image, out *image.RGBA64, r int) {
	//var iarr = 1 / (r+r+1);
	var (
		iarr   = 1.0 / float64(2*r+1)
		top    = in.Bounds().Min.Y
		bottom = in.Bounds().Max.Y
		left   = in.Bounds().Min.X
		right  = in.Bounds().Max.X
	)

	//for(var i=0; i<h; i++) {
	for i := top; i < bottom; i++ {
		//var ti = i*w, li = ti, ri = ti+r;
		//var fv = scl[ti], lv = scl[ti+w-1], val = (r+1)*fv;
		var (
			ti  = left
			li  = left
			ri  = left + r
			fv  = newColorVal(in.At(left, i))
			lv  = newColorVal(in.At(right, i))
			val = fv.times(float64(r + 1))
		)

		//for(var j=0; j<r; j++) val += scl[ti+j];
		for j := left; j < left+r; j++ {
			val.increment(newColorVal(in.At(i, j)))
		}

		//for(var j=0  ; j<=r ; j++) { val += scl[ri++] - fv       ;   tcl[ti++] = Math.round(val*iarr); }
		for j := left; j <= left+r; j++ {
			val.increment(newColorVal(in.At(i, ri)))
			val.decrement(fv)
			ri++
			out.Set(i, ti, val.asColor(iarr))
			ti++
		}

		//for(var j=r+1; j<w-r; j++) { val += scl[ri++] - scl[li++];   tcl[ti++] = Math.round(val*iarr); }
		for j := left + r + 1; j < right-r; j++ {
			val.increment(newColorVal(in.At(i, ri)))
			val.decrement(newColorVal(in.At(i, li)))
			ri++
			li++
			out.Set(i, ti, val.asColor(iarr))
			ti++
		}

		//for(var j=w-r; j<w  ; j++) { val += lv        - scl[li++];   tcl[ti++] = Math.round(val*iarr); }
		for j := right - r; j < right; j++ {
			val.increment(lv)
			val.decrement(newColorVal(in.At(i, li)))
			li++
			out.Set(i, ti, val.asColor(iarr))
			ti++
		}
	}
}

func boxBlurTotal(in image.Image, out *image.RGBA64, r int) {
	//var iarr = 1 / (r+r+1);
	var (
		iarr   = 1.0 / float64(2*r+1)
		top    = in.Bounds().Min.Y
		bottom = in.Bounds().Max.Y
		left   = in.Bounds().Min.X
		right  = in.Bounds().Max.X
	)

	//for(var i=0; i<w; i++) {
	for i := left; i < right; i++ {
		//var ti = i, li = ti, ri = ti+r*w;
		//var fv = scl[ti], lv = scl[ti+w*(h-1)], val = (r+1)*fv;
		var (
			ti  = top
			li  = top
			ri  = top + r
			fv  = newColorVal(in.At(i, top))
			lv  = newColorVal(in.At(i, bottom))
			val = fv.times(float64(r + 1))
		)

		//for(var j=0; j<r; j++) val += scl[ti+j*w];
		for j := top; j < top+r; j++ {
			val.increment(newColorVal(in.At(i, j)))
		}

		//for(var j=0  ; j<=r ; j++) { val += scl[ri] - fv     ;  tcl[ti] = Math.round(val*iarr);  ri+=w; ti+=w; }
		for j := top; j <= top+r; j++ {
			val.increment(newColorVal(in.At(i, ri)))
			val.decrement(fv)
			out.Set(i, ti, val.asColor(iarr))
			ri++
			ti++
		}

		//for(var j=r+1; j<h-r; j++) { val += scl[ri] - scl[li];  tcl[ti] = Math.round(val*iarr);  li+=w; ri+=w; ti+=w; }
		for j := top + r + 1; j < bottom-r; j++ {
			val.increment(newColorVal(in.At(i, ri)))
			val.decrement(newColorVal(in.At(i, li)))
			out.Set(i, ti, val.asColor(iarr))
			li++
			ri++
			ti++
		}

		//for(var j=h-r; j<h  ; j++) { val += lv      - scl[li];  tcl[ti] = Math.round(val*iarr);  li+=w; ti+=w; }
		for j := bottom - r; j < bottom; j++ {
			val.increment(lv)
			val.decrement(newColorVal(in.At(i, li)))
			out.Set(i, ti, val.asColor(iarr))
			li++
			ti++
		}
	}
}

func boxesForGauss(sigma float64, n int) (sizes []int) {
	wIdeal := math.Sqrt((12.0 * sigma * sigma / float64(n)) + 1.0) // Ideal averaging filter width
	wl := int(math.Floor(wIdeal))
	if wl%2 == 0 {
		wl--
	}
	wu := wl + 2

	mIdeal := (12.0*sigma*sigma - float64(n*wl*wl+4*n*wl+3*n)) / float64(-4*wl-4)
	m := math.Round(mIdeal)
	// var sigmaActual = Math.sqrt( (m*wl*wl + (n-m)*wu*wu - n)/12 );

	sizes = make([]int, n)
	for i := range sizes {
		if float64(i) < m {
			sizes[i] = wl
		} else {
			sizes[i] = wu
		}
	}
	return
}

type colorVal struct {
	r, g, b, a float64
}

func newColorVal(c color.Color) (out *colorVal) {
	r, g, b, a := c.RGBA()
	out = &colorVal{
		r: float64(r),
		g: float64(g),
		b: float64(b),
		a: float64(a),
	}
	return
}

func (v *colorVal) times(n float64) (product *colorVal) {
	product = &colorVal{
		r: v.r * n,
		g: v.g * n,
		b: v.b * n,
		a: v.a * n,
	}
	return
}

func (v *colorVal) increment(n *colorVal) {
	v.r += n.r
	v.g += n.g
	v.b += n.b
	v.a += n.a
}

func (v *colorVal) decrement(n *colorVal) {
	v.r -= n.r
	v.g -= n.g
	v.b -= n.b
	v.a -= n.a
}

func (v *colorVal) asColor(factor float64) color.Color {
	return &color.RGBA64{
		R: uint16(math.Round(v.r * factor)),
		G: uint16(math.Round(v.g * factor)),
		B: uint16(math.Round(v.b * factor)),
		A: uint16(math.Round(v.a * factor)),
	}
}
<|endoftext|>