<commit_before>package analytics

import (
	"encoding/json"
	"net"
	"reflect"
)

// This type provides the representation of the `context` object as defined in
// https://segment.com/docs/spec/common/#context
type Context struct {
	App       AppInfo      `json:"app,omitempty"`
	Campaign  CampaignInfo `json:"campaign,omitempty"`
	Device    DeviceInfo   `json:"device,omitempty"`
	Library   LibraryInfo  `json:"library,omitempty"`
	Location  LocationInfo `json:"location,omitempty"`
	Network   NetworkInfo  `json:"network,omitempty"`
	OS        OSInfo       `json:"os,omitempty"`
	Page      PageInfo     `json:"page,omitempty"`
	Referrer  ReferrerInfo `json:"referrer,omitempty"`
	Screen    ScreenInfo   `json:"screen,omitempty"`
	IP        net.IP       `json:"ip,omitempty"`
	Locale    string       `json:"locale,omitempty"`
	Timezone  string       `json:"timezone,omitempty"`
	UserAgent string       `json:"userAgent,omitempty"`
	Traits    Traits       `json:"traits,omitempty"`

	// This map is used to allow extensions to the context specifications that
	// may not be documented or could be introduced in the future.
	// The fields of this map are inlined in the serialized context object,
	// there is no actual "extra" field in the JSON representation.
	Extra map[string]interface{} `json:"-"`
}

// This type provides the representation of the `context.app` object as defined
// in https://segment.com/docs/spec/common/#context
type AppInfo struct {
	Name      string `json:"name,omitempty"`
	Version   string `json:"version,omitempty"`
	Build     string `json:"build,omitempty"`
	Namespace string `json:"namespace,omitempty"`
}

// This type provides the representation of the `context.campaign` object as
// defined in https://segment.com/docs/spec/common/#context
type CampaignInfo struct {
	Name    string `json:"name,omitempty"`
	Source  string `json:"source,omitempty"`
	Medium  string `json:"medium,omitempty"`
	Term    string `json:"term,omitempty"`
	Content string `json:"content,omitempty"`
}

// This type provides the representation of the `context.device` object as
// defined in https://segment.com/docs/spec/common/#context
type DeviceInfo struct {
	Id            string `json:"id,omitempty"`
	Manufacturer  string `json:"manufacturer,omitempty"`
	Model         string `json:"model,omitempty"`
	Name          string `json:"name,omitempty"`
	Type          string `json:"type,omitempty"`
	Version       string `json:"version,omitempty"`
	AdvertisingID string `json:"advertisingId,omitempty"`
}

// This type provides the representation of the `context.library` object as
// defined in https://segment.com/docs/spec/common/#context
type LibraryInfo struct {
	Name    string `json:"name,omitempty"`
	Version string `json:"version,omitempty"`
}

// This type provides the representation of the `context.location` object as
// defined in https://segment.com/docs/spec/common/#context
type LocationInfo struct {
	City      string  `json:"city,omitempty"`
	Country   string  `json:"country,omitempty"`
	Region    string  `json:"region,omitempty"`
	Latitude  float64 `json:"latitude,omitempty"`
	Longitude float64 `json:"longitude,omitempty"`
	Speed     float64 `json:"speed,omitempty"`
}

// This type provides the representation of the `context.network` object as
// defined in https://segment.com/docs/spec/common/#context
type NetworkInfo struct {
	Bluetooth bool   `json:"bluetooth,omitempty"`
	Cellular  bool   `json:"cellular,omitempty"`
	WIFI      bool   `json:"wifi,omitempty"`
	Carrier   string `json:"carrier,omitempty"`
}

// This type provides the representation of the `context.os` object as defined
// in https://segment.com/docs/spec/common/#context
type OSInfo struct {
	Name    string `json:"name,omitempty"`
	Version string `json:"version,omitempty"`
}

// This type provides the representation of the `context.page` object as
// defined in https://segment.com/docs/spec/common/#context
type PageInfo struct {
	Hash     string `json:"hash,omitempty"`
	Path     string `json:"path,omitempty"`
	Referrer string `json:"referrer,omitempty"`
	Search   string `json:"search,omitempty"`
	Title    string `json:"title,omitempty"`
	URL      string `json:"url,omitempty"`
}

// This type provides the representation of the `context.referrer` object as
// defined in https://segment.com/docs/spec/common/#context
type ReferrerInfo struct {
	Type string `json:"type,omitempty"`
	Name string `json:"name,omitempty"`
	URL  string `json:"url,omitempty"`
	Link string `json:"link,omitempty"`
}

// This type provides the representation of the `context.screen` object as
// defined in https://segment.com/docs/spec/common/#context
type ScreenInfo struct {
	Density int `json:"density,omitempty"`
	Width   int `json:"width,omitempty"`
	Height  int `json:"height,omitempty"`
}

// Satisfy the `json.Marshaler` interface. We have to flatten out the `Extra`
// field but the standard json package doesn't support it yet.
// Implementing this interface allows us to override the default marshaling of
// the context object and to the inlining ourselves.
//
// Related discussion: https://github.com/golang/go/issues/6213
func (ctx Context) MarshalJSON() ([]byte, error) {
	v := reflect.ValueOf(ctx)
	n := v.NumField()
	m := make(map[string]interface{}, n+len(ctx.Extra))

	// Copy the `Extra` map into the map representation of the context, it is
	// important to do this operation before going through the actual struct
	// fields so the latter take precendence and override duplicated values
	// that would be set in the extensions.
	for name, value := range ctx.Extra {
		m[name] = value
	}

	return json.Marshal(structToMap(v, m))
}
<commit_msg>Add Context.Direct<commit_after>package analytics

import (
	"encoding/json"
	"net"
	"reflect"
)

// This type provides the representation of the `context` object as defined in
// https://segment.com/docs/spec/common/#context
type Context struct {
	App       AppInfo      `json:"app,omitempty"`
	Campaign  CampaignInfo `json:"campaign,omitempty"`
	Device    DeviceInfo   `json:"device,omitempty"`
	Library   LibraryInfo  `json:"library,omitempty"`
	Location  LocationInfo `json:"location,omitempty"`
	Network   NetworkInfo  `json:"network,omitempty"`
	OS        OSInfo       `json:"os,omitempty"`
	Page      PageInfo     `json:"page,omitempty"`
	Referrer  ReferrerInfo `json:"referrer,omitempty"`
	Screen    ScreenInfo   `json:"screen,omitempty"`
	IP        net.IP       `json:"ip,omitempty"`
	Direct    bool         `json:"direct,omitempty"`
	Locale    string       `json:"locale,omitempty"`
	Timezone  string       `json:"timezone,omitempty"`
	UserAgent string       `json:"userAgent,omitempty"`
	Traits    Traits       `json:"traits,omitempty"`

	// This map is used to allow extensions to the context specifications that
	// may not be documented or could be introduced in the future.
	// The fields of this map are inlined in the serialized context object,
	// there is no actual "extra" field in the JSON representation.
	Extra map[string]interface{} `json:"-"`
}

// This type provides the representation of the `context.app` object as defined
// in https://segment.com/docs/spec/common/#context
type AppInfo struct {
	Name      string `json:"name,omitempty"`
	Version   string `json:"version,omitempty"`
	Build     string `json:"build,omitempty"`
	Namespace string `json:"namespace,omitempty"`
}

// This type provides the representation of the `context.campaign` object as
// defined in https://segment.com/docs/spec/common/#context
type CampaignInfo struct {
	Name    string `json:"name,omitempty"`
	Source  string `json:"source,omitempty"`
	Medium  string `json:"medium,omitempty"`
	Term    string `json:"term,omitempty"`
	Content string `json:"content,omitempty"`
}

// This type provides the representation of the `context.device` object as
// defined in https://segment.com/docs/spec/common/#context
type DeviceInfo struct {
	Id            string `json:"id,omitempty"`
	Manufacturer  string `json:"manufacturer,omitempty"`
	Model         string `json:"model,omitempty"`
	Name          string `json:"name,omitempty"`
	Type          string `json:"type,omitempty"`
	Version       string `json:"version,omitempty"`
	AdvertisingID string `json:"advertisingId,omitempty"`
}

// This type provides the representation of the `context.library` object as
// defined in https://segment.com/docs/spec/common/#context
type LibraryInfo struct {
	Name    string `json:"name,omitempty"`
	Version string `json:"version,omitempty"`
}

// This type provides the representation of the `context.location` object as
// defined in https://segment.com/docs/spec/common/#context
type LocationInfo struct {
	City      string  `json:"city,omitempty"`
	Country   string  `json:"country,omitempty"`
	Region    string  `json:"region,omitempty"`
	Latitude  float64 `json:"latitude,omitempty"`
	Longitude float64 `json:"longitude,omitempty"`
	Speed     float64 `json:"speed,omitempty"`
}

// This type provides the representation of the `context.network` object as
// defined in https://segment.com/docs/spec/common/#context
type NetworkInfo struct {
	Bluetooth bool   `json:"bluetooth,omitempty"`
	Cellular  bool   `json:"cellular,omitempty"`
	WIFI      bool   `json:"wifi,omitempty"`
	Carrier   string `json:"carrier,omitempty"`
}

// This type provides the representation of the `context.os` object as defined
// in https://segment.com/docs/spec/common/#context
type OSInfo struct {
	Name    string `json:"name,omitempty"`
	Version string `json:"version,omitempty"`
}

// This type provides the representation of the `context.page` object as
// defined in https://segment.com/docs/spec/common/#context
type PageInfo struct {
	Hash     string `json:"hash,omitempty"`
	Path     string `json:"path,omitempty"`
	Referrer string `json:"referrer,omitempty"`
	Search   string `json:"search,omitempty"`
	Title    string `json:"title,omitempty"`
	URL      string `json:"url,omitempty"`
}

// This type provides the representation of the `context.referrer` object as
// defined in https://segment.com/docs/spec/common/#context
type ReferrerInfo struct {
	Type string `json:"type,omitempty"`
	Name string `json:"name,omitempty"`
	URL  string `json:"url,omitempty"`
	Link string `json:"link,omitempty"`
}

// This type provides the representation of the `context.screen` object as
// defined in https://segment.com/docs/spec/common/#context
type ScreenInfo struct {
	Density int `json:"density,omitempty"`
	Width   int `json:"width,omitempty"`
	Height  int `json:"height,omitempty"`
}

// Satisfy the `json.Marshaler` interface. We have to flatten out the `Extra`
// field but the standard json package doesn't support it yet.
// Implementing this interface allows us to override the default marshaling of
// the context object and to the inlining ourselves.
//
// Related discussion: https://github.com/golang/go/issues/6213
func (ctx Context) MarshalJSON() ([]byte, error) {
	v := reflect.ValueOf(ctx)
	n := v.NumField()
	m := make(map[string]interface{}, n+len(ctx.Extra))

	// Copy the `Extra` map into the map representation of the context, it is
	// important to do this operation before going through the actual struct
	// fields so the latter take precendence and override duplicated values
	// that would be set in the extensions.
	for name, value := range ctx.Extra {
		m[name] = value
	}

	return json.Marshal(structToMap(v, m))
}
<|endoftext|>


<commit_before>package widget

import (
	"fmt"
	"html/template"
	"reflect"

	"github.com/jinzhu/gorm"
	"github.com/qor/admin"
	"github.com/qor/qor"
	"github.com/qor/qor/utils"
)

// Context widget context
type Context struct {
	Widgets          *Widgets
	DB               *gorm.DB
	AvailableWidgets []string
	Options          map[string]interface{}
	InlineEdit       bool
	SourceType       string
	SourceID         string
	FuncMaps         template.FuncMap
	WidgetSetting    QorWidgetSettingInterface
}

// Get get option with name
func (context Context) Get(name string) (interface{}, bool) {
	if value, ok := context.Options[name]; ok {
		return value, true
	}

	return nil, false
}

// Set set option by name
func (context *Context) Set(name string, value interface{}) {
	if context.Options == nil {
		context.Options = map[string]interface{}{}
	}
	context.Options[name] = value
}

// GetDB set option by name
func (context *Context) GetDB() *gorm.DB {
	if context.DB != nil {
		return context.DB
	}
	return context.Widgets.Config.DB
}

// Clone clone a context
func (context *Context) Clone() *Context {
	return &Context{
		Widgets:          context.Widgets,
		DB:               context.DB,
		AvailableWidgets: context.AvailableWidgets,
		Options:          context.Options,
		InlineEdit:       context.InlineEdit,
		FuncMaps:         context.FuncMaps,
		WidgetSetting:    context.WidgetSetting,
	}
}

// Render render widget based on context
func (context *Context) Render(widgetName string, widgetGroupName string) template.HTML {
	var (
		visibleScopes         []string
		widgets               = context.Widgets
		widgetSettingResource = widgets.WidgetSettingResource
		clone                 = context.Clone()
	)

	for _, scope := range registeredScopes {
		if scope.Visible(context) {
			visibleScopes = append(visibleScopes, scope.ToParam())
		}
	}

	if setting := context.findWidgetSetting(widgetName, append(visibleScopes, "default"), widgetGroupName); setting != nil {
		clone.WidgetSetting = setting
		adminContext := admin.Context{Admin: context.Widgets.Config.Admin, Context: &qor.Context{DB: context.DB}}

		var (
			widgetObj     = GetWidget(setting.GetSerializableArgumentKind())
			widgetSetting = widgetObj.Context(clone, setting.GetSerializableArgument(setting))
			inlineEditURL = adminContext.URLFor(setting, widgetSettingResource)
		)

		if clone.InlineEdit {
			prefix := widgets.Resource.GetAdmin().GetRouter().Prefix

			return template.HTML(fmt.Sprintf(
				"
\n%v\n
",
				prefix,
				prefix,
				utils.ToParamString(widgetObj.Name),
				fmt.Sprintf("%v/%v/inline-edit", prefix, widgets.Resource.ToParam()),
				inlineEditURL,
				widgetObj.Render(widgetSetting, setting.GetTemplate()),
			))
		}

		return widgetObj.Render(widgetSetting, setting.GetTemplate())
	}

	return template.HTML("")
}

func (context *Context) findWidgetSetting(widgetName string, scopes []string, widgetGroupName string) QorWidgetSettingInterface {
	var (
		db                    = context.GetDB()
		widgetSettingResource = context.Widgets.WidgetSettingResource
		setting               QorWidgetSettingInterface
		settings              = widgetSettingResource.NewSlice()
	)

	if context.SourceID != "" {
		db.Order("source_id DESC").Where("name = ? AND scope IN (?) AND ((shared = ? AND source_type = ?) OR (source_type = ? AND source_id = ?))", widgetName, scopes, true, "", context.SourceType, context.SourceID).Find(settings)
	} else {
		db.Debug().Where("name = ? AND scope IN (?) AND source_type = ?", widgetName, scopes, "").Find(settings)
	}

	settingsValue := reflect.Indirect(reflect.ValueOf(settings))
	if settingsValue.Len() > 0 {
	OUTTER:
		for _, scope := range scopes {
			for i := 0; i < settingsValue.Len(); i++ {
				s := settingsValue.Index(i).Interface().(QorWidgetSettingInterface)
				if s.GetScope() == scope {
					setting = s
					break OUTTER
				}
			}
		}
	}

	if context.SourceType == "" {
		if setting == nil {
			if widgetGroupName == "" {
				utils.ExitWithMsg("Widget: Can't Create Widget Without Widget Type")
				return nil
			}
			setting = widgetSettingResource.NewStruct().(QorWidgetSettingInterface)
			setting.SetWidgetName(widgetName)
			setting.SetGroupName(widgetGroupName)
			setting.SetSerializableArgumentKind(widgetGroupName)
			db.Create(setting)
		} else if setting.GetGroupName() != widgetGroupName {
			setting.SetGroupName(widgetGroupName)
			db.Save(setting)
		}
	}

	return setting
}
<commit_msg>Remove debug code<commit_after>package widget

import (
	"fmt"
	"html/template"
	"reflect"

	"github.com/jinzhu/gorm"
	"github.com/qor/admin"
	"github.com/qor/qor"
	"github.com/qor/qor/utils"
)

// Context widget context
type Context struct {
	Widgets          *Widgets
	DB               *gorm.DB
	AvailableWidgets []string
	Options          map[string]interface{}
	InlineEdit       bool
	SourceType       string
	SourceID         string
	FuncMaps         template.FuncMap
	WidgetSetting    QorWidgetSettingInterface
}

// Get get option with name
func (context Context) Get(name string) (interface{}, bool) {
	if value, ok := context.Options[name]; ok {
		return value, true
	}

	return nil, false
}

// Set set option by name
func (context *Context) Set(name string, value interface{}) {
	if context.Options == nil {
		context.Options = map[string]interface{}{}
	}
	context.Options[name] = value
}

// GetDB set option by name
func (context *Context) GetDB() *gorm.DB {
	if context.DB != nil {
		return context.DB
	}
	return context.Widgets.Config.DB
}

// Clone clone a context
func (context *Context) Clone() *Context {
	return &Context{
		Widgets:          context.Widgets,
		DB:               context.DB,
		AvailableWidgets: context.AvailableWidgets,
		Options:          context.Options,
		InlineEdit:       context.InlineEdit,
		FuncMaps:         context.FuncMaps,
		WidgetSetting:    context.WidgetSetting,
	}
}

// Render render widget based on context
func (context *Context) Render(widgetName string, widgetGroupName string) template.HTML {
	var (
		visibleScopes         []string
		widgets               = context.Widgets
		widgetSettingResource = widgets.WidgetSettingResource
		clone                 = context.Clone()
	)

	for _, scope := range registeredScopes {
		if scope.Visible(context) {
			visibleScopes = append(visibleScopes, scope.ToParam())
		}
	}

	if setting := context.findWidgetSetting(widgetName, append(visibleScopes, "default"), widgetGroupName); setting != nil {
		clone.WidgetSetting = setting
		adminContext := admin.Context{Admin: context.Widgets.Config.Admin, Context: &qor.Context{DB: context.DB}}

		var (
			widgetObj     = GetWidget(setting.GetSerializableArgumentKind())
			widgetSetting = widgetObj.Context(clone, setting.GetSerializableArgument(setting))
			inlineEditURL = adminContext.URLFor(setting, widgetSettingResource)
		)

		if clone.InlineEdit {
			prefix := widgets.Resource.GetAdmin().GetRouter().Prefix

			return template.HTML(fmt.Sprintf(
				"
\n%v\n
",
				prefix,
				prefix,
				utils.ToParamString(widgetObj.Name),
				fmt.Sprintf("%v/%v/inline-edit", prefix, widgets.Resource.ToParam()),
				inlineEditURL,
				widgetObj.Render(widgetSetting, setting.GetTemplate()),
			))
		}

		return widgetObj.Render(widgetSetting, setting.GetTemplate())
	}

	return template.HTML("")
}

func (context *Context) findWidgetSetting(widgetName string, scopes []string, widgetGroupName string) QorWidgetSettingInterface {
	var (
		db                    = context.GetDB()
		widgetSettingResource = context.Widgets.WidgetSettingResource
		setting               QorWidgetSettingInterface
		settings              = widgetSettingResource.NewSlice()
	)

	if context.SourceID != "" {
		db.Order("source_id DESC").Where("name = ? AND scope IN (?) AND ((shared = ? AND source_type = ?) OR (source_type = ? AND source_id = ?))", widgetName, scopes, true, "", context.SourceType, context.SourceID).Find(settings)
	} else {
		db.Where("name = ? AND scope IN (?) AND source_type = ?", widgetName, scopes, "").Find(settings)
	}

	settingsValue := reflect.Indirect(reflect.ValueOf(settings))
	if settingsValue.Len() > 0 {
	OUTTER:
		for _, scope := range scopes {
			for i := 0; i < settingsValue.Len(); i++ {
				s := settingsValue.Index(i).Interface().(QorWidgetSettingInterface)
				if s.GetScope() == scope {
					setting = s
					break OUTTER
				}
			}
		}
	}

	if context.SourceType == "" {
		if setting == nil {
			if widgetGroupName == "" {
				utils.ExitWithMsg("Widget: Can't Create Widget Without Widget Type")
				return nil
			}
			setting = widgetSettingResource.NewStruct().(QorWidgetSettingInterface)
			setting.SetWidgetName(widgetName)
			setting.SetGroupName(widgetGroupName)
			setting.SetSerializableArgumentKind(widgetGroupName)
			db.Create(setting)
		} else if setting.GetGroupName() != widgetGroupName {
			setting.SetGroupName(widgetGroupName)
			db.Save(setting)
		}
	}

	return setting
}
<|endoftext|>


<commit_before>// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"go/build"
	"os"
	"path/filepath"
	"strings"

	"github.com/Masterminds/vcs"
	"github.com/pkg/errors"
	"github.com/sdboyer/gps"
)

// ctx defines the supporting context of the tool.
type ctx struct {
	GOPATH string // Go path
}

// newContext creates a struct with the project's GOPATH. It assumes
// that of your "GOPATH"'s we want the one we are currently in.
func newContext() (*ctx, error) {
	// this way we get the default GOPATH that was added in 1.8
	buildContext := build.Default
	wd, err := os.Getwd()
	if err != nil {
		return nil, errors.Wrap(err, "getting work directory")
	}
	for _, gp := range filepath.SplitList(buildContext.GOPATH) {
		if strings.HasPrefix(wd, gp) {
			return &ctx{GOPATH: gp}, nil
		}
	}

	return nil, errors.New("project not in a GOPATH")
}

func (c *ctx) sourceManager() (*gps.SourceMgr, error) {
	return gps.NewSourceManager(analyzer{}, filepath.Join(c.GOPATH, "pkg", "dep"))
}

// loadProject searches for a project root from the provided path, then loads
// the manifest and lock (if any) it finds there.
//
// If the provided path is empty, it will search from the path indicated by
// os.Getwd().
func (c *ctx) loadProject(path string) (*project, error) {
	var err error
	p := new(project)

	switch path {
	case "":
		p.absroot, err = findProjectRootFromWD()
	default:
		p.absroot, err = findProjectRoot(path)
	}

	if err != nil {
		return p, err
	}

	ip, err := c.splitAbsoluteProjectRoot(p.absroot)
	if err != nil {
		return nil, errors.Wrap(err, "split absolute project root")
	}
	p.importroot = gps.ProjectRoot(ip)

	mp := filepath.Join(p.absroot, manifestName)
	mf, err := os.Open(mp)
	if err != nil {
		if os.IsNotExist(err) {
			// TODO: list possible solutions? (dep init, cd $project)
			return nil, fmt.Errorf("no %v found in project root %v", manifestName, p.absroot)
		}
		// Unable to read the manifest file
		return nil, err
	}
	defer mf.Close()

	p.m, err = readManifest(mf)
	if err != nil {
		return nil, fmt.Errorf("error while parsing %s: %s", mp, err)
	}

	lp := filepath.Join(path, lockName)
	lf, err := os.Open(lp)
	if err != nil {
		if os.IsNotExist(err) {
			// It's fine for the lock not to exist
			return p, nil
		}
		// But if a lock does exist and we can't open it, that's a problem
		return nil, fmt.Errorf("could not open %s: %s", lp, err)
	}

	defer lf.Close()
	p.l, err = readLock(lf)
	if err != nil {
		return nil, fmt.Errorf("error while parsing %s: %s", lp, err)
	}

	return p, nil
}

// splitAbsoluteProjectRoot takes an absolute path and compares it against declared
// GOPATH(s) to determine what portion of the input path should be treated as an
// import path - as a project root.
//
// The second returned string indicates which GOPATH value was used.
func (c *ctx) splitAbsoluteProjectRoot(path string) (string, error) {
	srcprefix := filepath.Join(c.GOPATH, "src") + string(filepath.Separator)
	if strings.HasPrefix(path, srcprefix) {
		// filepath.ToSlash because we're dealing with an import path now,
		// not an fs path
		return filepath.ToSlash(strings.TrimPrefix(path, srcprefix)), nil
	}

	return "", fmt.Errorf("%s not in any $GOPATH", path)
}

// absoluteProjectRoot determines the absolute path to the project root
// including the $GOPATH. This will not work with stdlib packages and the
// package directory needs to exist.
func (c *ctx) absoluteProjectRoot(path string) (string, error) {
	posspath := filepath.Join(c.GOPATH, "src", path)
	dirOK, err := isDir(posspath)
	if err != nil {
		return "", errors.Wrapf(err, "checking if %s is a directory", posspath)
	}

	if !dirOK {
		return "", fmt.Errorf("%s does not exist", posspath)
	}

	return posspath, nil
}

func (c *ctx) versionInWorkspace(root gps.ProjectRoot) (gps.Version, error) {
	pr, err := c.absoluteProjectRoot(string(root))
	if err != nil {
		return nil, errors.Wrapf(err, "determine project root for %s", root)
	}

	repo, err := vcs.NewRepo("", string(pr))
	if err != nil {
		return nil, errors.Wrapf(err, "creating new repo for root: %s", pr)
	}

	ver, err := repo.Current()
	if err != nil {
		return nil, errors.Wrapf(err, "finding current branch/version for root: %s", pr)
	}

	rev, err := repo.Version()
	if err != nil {
		return nil, errors.Wrapf(err, "getting repo version for root: %s", pr)
	}

	// first look through tags
	tags, err := repo.Tags()
	if err != nil {
		return nil, errors.Wrapf(err, "getting repo tags for root: %s", pr)
	}
	// try to match the current version to a tag
	if contains(tags, ver) {
		// assume semver if it starts with a v
		if strings.HasPrefix(ver, "v") {
			return gps.NewVersion(ver).Is(gps.Revision(rev)), nil
		}

		return nil, fmt.Errorf("version for root %s does not start with a v: %q", pr, ver)
	}

	// look for the current branch
	branches, err := repo.Branches()
	if err != nil {
		return nil, errors.Wrapf(err, "getting repo branch for root: %s")
	}
	// try to match the current version to a branch
	if contains(branches, ver) {
		return gps.NewBranch(ver).Is(gps.Revision(rev)), nil
	}

	return gps.Revision(rev), nil
}
<commit_msg>Remove unnecessary conversion<commit_after>// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

import (
	"fmt"
	"go/build"
	"os"
	"path/filepath"
	"strings"

	"github.com/Masterminds/vcs"
	"github.com/pkg/errors"
	"github.com/sdboyer/gps"
)

// ctx defines the supporting context of the tool.
type ctx struct {
	GOPATH string // Go path
}

// newContext creates a struct with the project's GOPATH. It assumes
// that of your "GOPATH"'s we want the one we are currently in.
func newContext() (*ctx, error) {
	// this way we get the default GOPATH that was added in 1.8
	buildContext := build.Default
	wd, err := os.Getwd()
	if err != nil {
		return nil, errors.Wrap(err, "getting work directory")
	}
	for _, gp := range filepath.SplitList(buildContext.GOPATH) {
		if strings.HasPrefix(wd, gp) {
			return &ctx{GOPATH: gp}, nil
		}
	}

	return nil, errors.New("project not in a GOPATH")
}

func (c *ctx) sourceManager() (*gps.SourceMgr, error) {
	return gps.NewSourceManager(analyzer{}, filepath.Join(c.GOPATH, "pkg", "dep"))
}

// loadProject searches for a project root from the provided path, then loads
// the manifest and lock (if any) it finds there.
//
// If the provided path is empty, it will search from the path indicated by
// os.Getwd().
func (c *ctx) loadProject(path string) (*project, error) {
	var err error
	p := new(project)

	switch path {
	case "":
		p.absroot, err = findProjectRootFromWD()
	default:
		p.absroot, err = findProjectRoot(path)
	}

	if err != nil {
		return p, err
	}

	ip, err := c.splitAbsoluteProjectRoot(p.absroot)
	if err != nil {
		return nil, errors.Wrap(err, "split absolute project root")
	}
	p.importroot = gps.ProjectRoot(ip)

	mp := filepath.Join(p.absroot, manifestName)
	mf, err := os.Open(mp)
	if err != nil {
		if os.IsNotExist(err) {
			// TODO: list possible solutions? (dep init, cd $project)
			return nil, fmt.Errorf("no %v found in project root %v", manifestName, p.absroot)
		}
		// Unable to read the manifest file
		return nil, err
	}
	defer mf.Close()

	p.m, err = readManifest(mf)
	if err != nil {
		return nil, fmt.Errorf("error while parsing %s: %s", mp, err)
	}

	lp := filepath.Join(path, lockName)
	lf, err := os.Open(lp)
	if err != nil {
		if os.IsNotExist(err) {
			// It's fine for the lock not to exist
			return p, nil
		}
		// But if a lock does exist and we can't open it, that's a problem
		return nil, fmt.Errorf("could not open %s: %s", lp, err)
	}

	defer lf.Close()
	p.l, err = readLock(lf)
	if err != nil {
		return nil, fmt.Errorf("error while parsing %s: %s", lp, err)
	}

	return p, nil
}

// splitAbsoluteProjectRoot takes an absolute path and compares it against declared
// GOPATH(s) to determine what portion of the input path should be treated as an
// import path - as a project root.
//
// The second returned string indicates which GOPATH value was used.
func (c *ctx) splitAbsoluteProjectRoot(path string) (string, error) {
	srcprefix := filepath.Join(c.GOPATH, "src") + string(filepath.Separator)
	if strings.HasPrefix(path, srcprefix) {
		// filepath.ToSlash because we're dealing with an import path now,
		// not an fs path
		return filepath.ToSlash(strings.TrimPrefix(path, srcprefix)), nil
	}

	return "", fmt.Errorf("%s not in any $GOPATH", path)
}

// absoluteProjectRoot determines the absolute path to the project root
// including the $GOPATH. This will not work with stdlib packages and the
// package directory needs to exist.
func (c *ctx) absoluteProjectRoot(path string) (string, error) {
	posspath := filepath.Join(c.GOPATH, "src", path)
	dirOK, err := isDir(posspath)
	if err != nil {
		return "", errors.Wrapf(err, "checking if %s is a directory", posspath)
	}

	if !dirOK {
		return "", fmt.Errorf("%s does not exist", posspath)
	}

	return posspath, nil
}

func (c *ctx) versionInWorkspace(root gps.ProjectRoot) (gps.Version, error) {
	pr, err := c.absoluteProjectRoot(string(root))
	if err != nil {
		return nil, errors.Wrapf(err, "determine project root for %s", root)
	}

	repo, err := vcs.NewRepo("", pr)
	if err != nil {
		return nil, errors.Wrapf(err, "creating new repo for root: %s", pr)
	}

	ver, err := repo.Current()
	if err != nil {
		return nil, errors.Wrapf(err, "finding current branch/version for root: %s", pr)
	}

	rev, err := repo.Version()
	if err != nil {
		return nil, errors.Wrapf(err, "getting repo version for root: %s", pr)
	}

	// first look through tags
	tags, err := repo.Tags()
	if err != nil {
		return nil, errors.Wrapf(err, "getting repo tags for root: %s", pr)
	}
	// try to match the current version to a tag
	if contains(tags, ver) {
		// assume semver if it starts with a v
		if strings.HasPrefix(ver, "v") {
			return gps.NewVersion(ver).Is(gps.Revision(rev)), nil
		}

		return nil, fmt.Errorf("version for root %s does not start with a v: %q", pr, ver)
	}

	// look for the current branch
	branches, err := repo.Branches()
	if err != nil {
		return nil, errors.Wrapf(err, "getting repo branch for root: %s")
	}
	// try to match the current version to a branch
	if contains(branches, ver) {
		return gps.NewBranch(ver).Is(gps.Revision(rev)), nil
	}

	return gps.Revision(rev), nil
}
<|endoftext|>


<commit_before>package air

import (
	"bytes"
	"context"
	"encoding/json"
	"encoding/xml"
	"errors"
	"io"
	"mime"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"
	"reflect"
	"time"
)

// Context represents the context of the current HTTP request. It holds request and
// response objects, path, path parameters, data and registered handler.
type Context struct {
	goContext context.Context

	Request    *Request
	Response   *Response
	Path       string
	ParamNames []string
	Params     map[string]string
	Handler    HandlerFunc
	StatusCode int
	Data       JSONMap
	Air        *Air
}

// newContext returns a new instance of `Context`.
func newContext(a *Air) *Context {
	return &Context{
		goContext:  context.Background(),
		Params:     make(map[string]string),
		Handler:    NotFoundHandler,
		StatusCode: http.StatusOK,
		Data:       make(JSONMap),
		Air:        a,
	}
}

// Deadline returns the time when work done on behalf of this context
// should be canceled. Deadline returns ok==false when no deadline is
// set. Successive calls to Deadline return the same results.
func (c *Context) Deadline() (deadline time.Time, ok bool) {
	return c.goContext.Deadline()
}

// Done returns a channel that's closed when work done on behalf of this
// context should be canceled. Done may return nil if this context can
// never be canceled. Successive calls to Done return the same value.
func (c *Context) Done() <-chan struct{} {
	return c.goContext.Done()
}

// Err returns a non-nil error value after Done is closed. Err returns
// Canceled if the context was canceled or DeadlineExceeded if the
// context's deadline passed. No other values for Err are defined.
// After Done is closed, successive calls to Err return the same value.
func (c *Context) Err() error {
	return c.goContext.Err()
}

// Value returns the value associated with this context for key, or nil
// if no value is associated with key. Successive calls to Value with
// the same key returns the same result.
func (c *Context) Value(key interface{}) interface{} {
	return c.goContext.Value(key)
}

// SetValue sets request-scoped value into the context.
func (c *Context) SetValue(key interface{}, val interface{}) {
	c.goContext = context.WithValue(c.goContext, key, val)
}

// QueryParam returns the query param for the provided name. It is an alias
// for `URI#QueryParam()`.
func (c *Context) QueryParam(name string) string {
	return c.Request.URI.QueryParam(name)
}

// QueryParams returns the query parameters as map. It is an alias for
// `URI#QueryParams()`.
func (c *Context) QueryParams() map[string][]string {
	return c.Request.URI.QueryParams()
}

// FormValue returns the form field value for the provided name. It is an
// alias for `Request#FormValue()`.
func (c *Context) FormValue(name string) string {
	return c.Request.FormValue(name)
}

// FormParams returns the form parameters as map.
// It is an alias for `Request#FormParams()`.
func (c *Context) FormParams() map[string][]string {
	return c.Request.FormParams()
}

// FormFile returns the multipart form file for the provided name. It is an
// alias for `Request#FormFile()`.
func (c *Context) FormFile(name string) (*multipart.FileHeader, error) {
	return c.Request.FormFile(name)
}

// MultipartForm returns the multipart form.
// It is an alias for `Request#MultipartForm()`.
func (c *Context) MultipartForm() (*multipart.Form, error) {
	return c.Request.MultipartForm()
}

// Cookie returns the named cookie provided in the request.
// It is an alias for `Request#Cookie()`.
func (c *Context) Cookie(name string) (Cookie, error) {
	return c.Request.Cookie(name)
}

// SetCookie adds a "Set-Cookie" header in HTTP response.
// It is an alias for `Response#SetCookie()`.
func (c *Context) SetCookie(cookie Cookie) {
	c.Response.SetCookie(cookie)
}

// Cookies returns the HTTP cookies sent with the request. It is an alias
// for `Request#Cookies()`.
func (c *Context) Cookies() []Cookie {
	return c.Request.Cookies()
}

// Bind binds the request body into provided type i. The default binder doe
// it based on "Content-Type" header.
func (c *Context) Bind(i interface{}) error {
	return c.Air.binder.bind(i, c)
}

// Render renders a template with `Context#Data` and `Context#Data["template"]`
// and sends a "text/html" response with `Context#StatusCode`.
func (c *Context) Render() (err error) {
	t, ok := c.Data["template"]
	if !ok || reflect.ValueOf(t).Kind() != reflect.String {
		return errors.New("c.Data[\"template\"] Not Setted")
	}
	buf := &bytes.Buffer{}
	if err = c.Air.renderer.render(buf, t.(string), c); err != nil {
		return
	}
	c.Response.Header.Set(HeaderContentType, MIMETextHTML)
	c.Response.WriteHeader(c.StatusCode)
	_, err = c.Response.Write(buf.Bytes())
	return
}

// HTML sends an HTTP response with `Context#StatusCode` and `Context#Data["html"]`.
func (c *Context) HTML() (err error) {
	h, ok := c.Data["html"]
	if !ok || reflect.ValueOf(h).Kind() != reflect.String {
		return errors.New("c.Data[\"html\"] Not Setted")
	}
	c.Response.Header.Set(HeaderContentType, MIMETextHTML)
	c.Response.WriteHeader(c.StatusCode)
	_, err = c.Response.Write([]byte(h.(string)))
	return
}

// String sends a string response with `Context#StatusCode` and `Context#Data["string"]`.
func (c *Context) String() (err error) {
	s, ok := c.Data["string"]
	if !ok || reflect.ValueOf(s).Kind() != reflect.String {
		return errors.New("c.Data[\"string\"] Not Setted")
	}
	c.Response.Header.Set(HeaderContentType, MIMETextPlain)
	c.Response.WriteHeader(c.StatusCode)
	_, err = c.Response.Write([]byte(s.(string)))
	return
}

// JSON sends a JSON response with `Context#StatusCode` and `Context#Data["json"]`.
func (c *Context) JSON() (err error) {
	j, ok := c.Data["json"]
	if !ok {
		return errors.New("c.Data[\"json\"] Not Setted")
	}
	b, err := json.Marshal(j)
	if c.Air.Config.DebugMode {
		b, err = json.MarshalIndent(j, "", "\t")
	}
	if err != nil {
		return err
	}
	return c.JSONBlob(b)
}

// JSONBlob sends a JSON blob response with `Context#StatusCode`.
func (c *Context) JSONBlob(b []byte) (err error) {
	c.Response.Header.Set(HeaderContentType, MIMEApplicationJSON)
	c.Response.WriteHeader(c.StatusCode)
	_, err = c.Response.Write(b)
	return
}

// JSONP sends a JSONP response with `Context#StatusCode` and `Context#Data["jsonp"]`.
// It uses `Context#Data["callback"]` to construct the JSONP payload.
func (c *Context) JSONP() (err error) {
	j, jok := c.Data["jsonp"]
	cb, cbok := c.Data["callback"]
	if !jok {
		return errors.New("c.Data[\"jsonp\"] Not Setted")
	} else if !cbok || reflect.ValueOf(cb).Kind() != reflect.String {
		return errors.New("c.Data[\"callback\"] Not Setted")
	}
	b, err := json.Marshal(j)
	if err != nil {
		return err
	}
	c.Response.Header.Set(HeaderContentType, MIMEApplicationJavaScript)
	c.Response.WriteHeader(c.StatusCode)
	if _, err = c.Response.Write([]byte(cb.(string) + "(")); err != nil {
		return
	}
	if _, err = c.Response.Write(b); err != nil {
		return
	}
	_, err = c.Response.Write([]byte(");"))
	return
}

// XML sends an XML response with `Context#StatusCode` and `Context#Data["xml"]`.
func (c *Context) XML() (err error) {
	x, ok := c.Data["xml"]
	if !ok {
		return errors.New("c.Data[\"xml\"] Not Setted")
	}
	b, err := xml.Marshal(x)
	if c.Air.Config.DebugMode {
		b, err = xml.MarshalIndent(x, "", "\t")
	}
	if err != nil {
		return err
	}
	return c.XMLBlob(b)
}

// XMLBlob sends a XML blob response with `Context#StatusCode`.
func (c *Context) XMLBlob(b []byte) (err error) {
	c.Response.Header.Set(HeaderContentType, MIMEApplicationXML)
	c.Response.WriteHeader(c.StatusCode)
	if _, err = c.Response.Write([]byte(xml.Header)); err != nil {
		return
	}
	_, err = c.Response.Write(b)
	return
}

// File sends a response with the content of the file.
func (c *Context) File(file string) error {
	f, err := os.Open(file)
	if err != nil {
		return ErrNotFound
	}
	defer f.Close()

	fi, _ := f.Stat()
	if fi.IsDir() {
		file = filepath.Join(file, "index.html")
		f, err = os.Open(file)
		if err != nil {
			return ErrNotFound
		}
		if fi, err = f.Stat(); err != nil {
			return err
		}
	}
	return c.ServeContent(f, fi.Name(), fi.ModTime())
}

// Attachment sends a response from `io.ReaderSeeker` as attachment, prompting
// client to save the file.
func (c *Context) Attachment(r io.ReadSeeker, name string) (err error) {
	c.Response.Header.Set(HeaderContentType, contentTypeByExtension(name))
	c.Response.Header.Set(HeaderContentDisposition, "attachment; filename="+name)
	c.Response.WriteHeader(http.StatusOK)
	_, err = io.Copy(c.Response, r)
	return
}

// NoContent sends a response with no body and a `Context#StatusCode`.
func (c *Context) NoContent() error {
	c.Response.WriteHeader(c.StatusCode)
	return nil
}

// Redirect redirects the request with `Context#StatusCode`.
func (c *Context) Redirect(uri string) error {
	if c.StatusCode < http.StatusMultipleChoices || c.StatusCode > http.StatusTemporaryRedirect {
		return ErrInvalidRedirectCode
	}
	c.Response.Header.Set(HeaderLocation, uri)
	c.Response.WriteHeader(c.StatusCode)
	return nil
}

// ServeContent sends static content from `io.Reader` and handles caching
// via "If-Modified-Since" request header. It automatically sets "Content-Type"
// and "Last-Modified" response headers.
func (c *Context) ServeContent(content io.ReadSeeker, name string, modtime time.Time) error {
	req := c.Request
	res := c.Response

	if t, err := time.Parse(http.TimeFormat, req.Header.Get(HeaderIfModifiedSince)); err == nil && modtime.Before(t.Add(1*time.Second)) {
		res.Header.Del(HeaderContentType)
		res.Header.Del(HeaderContentLength)
		c.StatusCode = http.StatusNotModified
		return c.NoContent()
	}

	res.Header.Set(HeaderContentType, contentTypeByExtension(name))
	res.Header.Set(HeaderLastModified, modtime.UTC().Format(http.TimeFormat))
	res.WriteHeader(http.StatusOK)
	_, err := io.Copy(res, content)
	return err
}

// reset resets the instance of `Context`.
func (c *Context) reset() {
	c.goContext = context.Background()
	c.Request = nil
	c.Response = nil
	c.Path = ""
	c.ParamNames = c.ParamNames[:0]
	for k := range c.Params {
		delete(c.Params, k)
	}
	c.Handler = NotFoundHandler
	c.StatusCode = http.StatusOK
	for k := range c.Data {
		delete(c.Data, k)
	}
}

// contentTypeByExtension returns the MIME type associated with the file based
// on its extension. It returns "application/octet-stream" incase MIME type is
// not found.
func contentTypeByExtension(name string) (t string) {
	if t = mime.TypeByExtension(filepath.Ext(name)); t == "" {
		t = MIMEOctetStream
	}
	return
}
<commit_msg>feat: add the response method `Context#Inline()`<commit_after>package air

import (
	"bytes"
	"context"
	"encoding/json"
	"encoding/xml"
	"errors"
	"io"
	"mime"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"
	"reflect"
	"time"
)

// Context represents the context of the current HTTP request. It holds request and
// response objects, path, path parameters, data and registered handler.
type Context struct {
	goContext context.Context

	Request    *Request
	Response   *Response
	Path       string
	ParamNames []string
	Params     map[string]string
	Handler    HandlerFunc
	StatusCode int
	Data       JSONMap
	Air        *Air
}

// newContext returns a new instance of `Context`.
func newContext(a *Air) *Context {
	return &Context{
		goContext:  context.Background(),
		Params:     make(map[string]string),
		Handler:    NotFoundHandler,
		StatusCode: http.StatusOK,
		Data:       make(JSONMap),
		Air:        a,
	}
}

// Deadline returns the time when work done on behalf of this context
// should be canceled. Deadline returns ok==false when no deadline is
// set. Successive calls to Deadline return the same results.
func (c *Context) Deadline() (deadline time.Time, ok bool) {
	return c.goContext.Deadline()
}

// Done returns a channel that's closed when work done on behalf of this
// context should be canceled. Done may return nil if this context can
// never be canceled. Successive calls to Done return the same value.
func (c *Context) Done() <-chan struct{} {
	return c.goContext.Done()
}

// Err returns a non-nil error value after Done is closed. Err returns
// Canceled if the context was canceled or DeadlineExceeded if the
// context's deadline passed. No other values for Err are defined.
// After Done is closed, successive calls to Err return the same value.
func (c *Context) Err() error {
	return c.goContext.Err()
}

// Value returns the value associated with this context for key, or nil
// if no value is associated with key. Successive calls to Value with
// the same key returns the same result.
func (c *Context) Value(key interface{}) interface{} {
	return c.goContext.Value(key)
}

// SetValue sets request-scoped value into the context.
func (c *Context) SetValue(key interface{}, val interface{}) {
	c.goContext = context.WithValue(c.goContext, key, val)
}

// QueryParam returns the query param for the provided name. It is an alias
// for `URI#QueryParam()`.
func (c *Context) QueryParam(name string) string {
	return c.Request.URI.QueryParam(name)
}

// QueryParams returns the query parameters as map. It is an alias for
// `URI#QueryParams()`.
func (c *Context) QueryParams() map[string][]string {
	return c.Request.URI.QueryParams()
}

// FormValue returns the form field value for the provided name. It is an
// alias for `Request#FormValue()`.
func (c *Context) FormValue(name string) string {
	return c.Request.FormValue(name)
}

// FormParams returns the form parameters as map.
// It is an alias for `Request#FormParams()`.
func (c *Context) FormParams() map[string][]string {
	return c.Request.FormParams()
}

// FormFile returns the multipart form file for the provided name. It is an
// alias for `Request#FormFile()`.
func (c *Context) FormFile(name string) (*multipart.FileHeader, error) {
	return c.Request.FormFile(name)
}

// MultipartForm returns the multipart form.
// It is an alias for `Request#MultipartForm()`.
func (c *Context) MultipartForm() (*multipart.Form, error) {
	return c.Request.MultipartForm()
}

// Cookie returns the named cookie provided in the request.
// It is an alias for `Request#Cookie()`.
func (c *Context) Cookie(name string) (Cookie, error) {
	return c.Request.Cookie(name)
}

// SetCookie adds a "Set-Cookie" header in HTTP response.
// It is an alias for `Response#SetCookie()`.
func (c *Context) SetCookie(cookie Cookie) {
	c.Response.SetCookie(cookie)
}

// Cookies returns the HTTP cookies sent with the request. It is an alias
// for `Request#Cookies()`.
func (c *Context) Cookies() []Cookie {
	return c.Request.Cookies()
}

// Bind binds the request body into provided type i. The default binder doe
// it based on "Content-Type" header.
func (c *Context) Bind(i interface{}) error {
	return c.Air.binder.bind(i, c)
}

// Render renders a template with `Context#Data` and `Context#Data["template"]`
// and sends a "text/html" response with `Context#StatusCode`.
func (c *Context) Render() (err error) {
	t, ok := c.Data["template"]
	if !ok || reflect.ValueOf(t).Kind() != reflect.String {
		return errors.New("c.Data[\"template\"] Not Setted")
	}
	buf := &bytes.Buffer{}
	if err = c.Air.renderer.render(buf, t.(string), c); err != nil {
		return
	}
	c.Response.Header.Set(HeaderContentType, MIMETextHTML)
	c.Response.WriteHeader(c.StatusCode)
	_, err = c.Response.Write(buf.Bytes())
	return
}

// HTML sends an HTTP response with `Context#StatusCode` and `Context#Data["html"]`.
func (c *Context) HTML() (err error) {
	h, ok := c.Data["html"]
	if !ok || reflect.ValueOf(h).Kind() != reflect.String {
		return errors.New("c.Data[\"html\"] Not Setted")
	}
	c.Response.Header.Set(HeaderContentType, MIMETextHTML)
	c.Response.WriteHeader(c.StatusCode)
	_, err = c.Response.Write([]byte(h.(string)))
	return
}

// String sends a string response with `Context#StatusCode` and `Context#Data["string"]`.
func (c *Context) String() (err error) {
	s, ok := c.Data["string"]
	if !ok || reflect.ValueOf(s).Kind() != reflect.String {
		return errors.New("c.Data[\"string\"] Not Setted")
	}
	c.Response.Header.Set(HeaderContentType, MIMETextPlain)
	c.Response.WriteHeader(c.StatusCode)
	_, err = c.Response.Write([]byte(s.(string)))
	return
}

// JSON sends a JSON response with `Context#StatusCode` and `Context#Data["json"]`.
func (c *Context) JSON() (err error) {
	j, ok := c.Data["json"]
	if !ok {
		return errors.New("c.Data[\"json\"] Not Setted")
	}
	b, err := json.Marshal(j)
	if c.Air.Config.DebugMode {
		b, err = json.MarshalIndent(j, "", "\t")
	}
	if err != nil {
		return err
	}
	return c.JSONBlob(b)
}

// JSONBlob sends a JSON blob response with `Context#StatusCode`.
func (c *Context) JSONBlob(b []byte) (err error) {
	c.Response.Header.Set(HeaderContentType, MIMEApplicationJSON)
	c.Response.WriteHeader(c.StatusCode)
	_, err = c.Response.Write(b)
	return
}

// JSONP sends a JSONP response with `Context#StatusCode` and `Context#Data["jsonp"]`.
// It uses `Context#Data["callback"]` to construct the JSONP payload.
func (c *Context) JSONP() (err error) {
	j, jok := c.Data["jsonp"]
	cb, cbok := c.Data["callback"]
	if !jok {
		return errors.New("c.Data[\"jsonp\"] Not Setted")
	} else if !cbok || reflect.ValueOf(cb).Kind() != reflect.String {
		return errors.New("c.Data[\"callback\"] Not Setted")
	}
	b, err := json.Marshal(j)
	if err != nil {
		return err
	}
	c.Response.Header.Set(HeaderContentType, MIMEApplicationJavaScript)
	c.Response.WriteHeader(c.StatusCode)
	if _, err = c.Response.Write([]byte(cb.(string) + "(")); err != nil {
		return
	}
	if _, err = c.Response.Write(b); err != nil {
		return
	}
	_, err = c.Response.Write([]byte(");"))
	return
}

// XML sends an XML response with `Context#StatusCode` and `Context#Data["xml"]`.
func (c *Context) XML() (err error) {
	x, ok := c.Data["xml"]
	if !ok {
		return errors.New("c.Data[\"xml\"] Not Setted")
	}
	b, err := xml.Marshal(x)
	if c.Air.Config.DebugMode {
		b, err = xml.MarshalIndent(x, "", "\t")
	}
	if err != nil {
		return err
	}
	return c.XMLBlob(b)
}

// XMLBlob sends a XML blob response with `Context#StatusCode`.
func (c *Context) XMLBlob(b []byte) (err error) {
	c.Response.Header.Set(HeaderContentType, MIMEApplicationXML)
	c.Response.WriteHeader(c.StatusCode)
	if _, err = c.Response.Write([]byte(xml.Header)); err != nil {
		return
	}
	_, err = c.Response.Write(b)
	return
}

// File sends a response with the content of the file.
func (c *Context) File(file string) error {
	f, err := os.Open(file)
	if err != nil {
		return ErrNotFound
	}
	defer f.Close()

	fi, _ := f.Stat()
	if fi.IsDir() {
		file = filepath.Join(file, "index.html")
		f, err = os.Open(file)
		if err != nil {
			return ErrNotFound
		}
		if fi, err = f.Stat(); err != nil {
			return err
		}
	}
	return c.ServeContent(f, fi.Name(), fi.ModTime())
}

// Attachment sends a response from `io.ReaderSeeker` as attachment, prompting
// client to save the file.
func (c *Context) Attachment(r io.ReadSeeker, name string) error {
	return c.contentDisposition(r, name, "attachment")
}

// Inline sends a response from `io.ReaderSeeker` as inline, opening the
// file in the browser.
func (c *Context) Inline(r io.ReadSeeker, name string) error {
	return c.contentDisposition(r, name, "inline")
}

// contentDisposition sends a response from `io.ReaderSeeker` as dispositionType.
func (c *Context) contentDisposition(r io.ReadSeeker, name, dispositionType string) (err error) {
	c.Response.Header.Set(HeaderContentType, contentTypeByExtension(name))
	c.Response.Header.Set(HeaderContentDisposition, dispositionType+"; filename="+name)
	c.Response.WriteHeader(http.StatusOK)
	_, err = io.Copy(c.Response, r)
	return
}

// NoContent sends a response with no body and a `Context#StatusCode`.
func (c *Context) NoContent() error {
	c.Response.WriteHeader(c.StatusCode)
	return nil
}

// Redirect redirects the request with `Context#StatusCode`.
func (c *Context) Redirect(uri string) error {
	if c.StatusCode < http.StatusMultipleChoices || c.StatusCode > http.StatusTemporaryRedirect {
		return ErrInvalidRedirectCode
	}
	c.Response.Header.Set(HeaderLocation, uri)
	c.Response.WriteHeader(c.StatusCode)
	return nil
}

// ServeContent sends static content from `io.Reader` and handles caching
// via "If-Modified-Since" request header. It automatically sets "Content-Type"
// and "Last-Modified" response headers.
func (c *Context) ServeContent(content io.ReadSeeker, name string, modtime time.Time) error {
	req := c.Request
	res := c.Response

	if t, err := time.Parse(http.TimeFormat, req.Header.Get(HeaderIfModifiedSince)); err == nil && modtime.Before(t.Add(1*time.Second)) {
		res.Header.Del(HeaderContentType)
		res.Header.Del(HeaderContentLength)
		c.StatusCode = http.StatusNotModified
		return c.NoContent()
	}

	res.Header.Set(HeaderContentType, contentTypeByExtension(name))
	res.Header.Set(HeaderLastModified, modtime.UTC().Format(http.TimeFormat))
	res.WriteHeader(http.StatusOK)
	_, err := io.Copy(res, content)
	return err
}

// reset resets the instance of `Context`.
func (c *Context) reset() {
	c.goContext = context.Background()
	c.Request = nil
	c.Response = nil
	c.Path = ""
	c.ParamNames = c.ParamNames[:0]
	for k := range c.Params {
		delete(c.Params, k)
	}
	c.Handler = NotFoundHandler
	c.StatusCode = http.StatusOK
	for k := range c.Data {
		delete(c.Data, k)
	}
}

// contentTypeByExtension returns the MIME type associated with the file based
// on its extension. It returns "application/octet-stream" incase MIME type is
// not found.
func contentTypeByExtension(name string) (t string) {
	if t = mime.TypeByExtension(filepath.Ext(name)); t == "" {
		t = MIMEOctetStream
	}
	return
}
<|endoftext|>


<commit_before>package ace

import (
	"encoding/json"
	"fmt"
	"github.com/julienschmidt/httprouter"
	"math"
	"net/http"
	"strings"
)

const (
	contentType    = "Content-Type"
	acceptLanguage = "Accept-Language"
	abortIndex     = math.MaxInt8 / 2
)

//C is context for every goroutine
type C struct {
	writercache      responseWriter
	Params           httprouter.Params
	Request          *http.Request
	Writer           ResponseWriter
	index            int8
	handlers         []HandlerFunc
	errorHandlerFunc ErrorHandlerFunc
	//recovery
	context map[string]interface{}
	err     error
	Session *session
	render  Renderer
}

func (a *Ace) CreateContext(w http.ResponseWriter, r *http.Request) *C {
	c := a.pool.Get().(*C)
	c.writercache.reset(w)
	c.Request = r
	c.context = nil
	c.index = -1
	c.render = a.render

	return c
}

//JSON response with application/json; charset=UTF-8 Content type
func (c *C) JSON(status int, v interface{}) {
	result, err := json.Marshal(v)
	if err != nil {
		panic(err)
	}

	c.Writer.Header().Set(contentType, "application/json; charset=UTF-8")
	c.Writer.WriteHeader(status)
	c.Writer.Write(result)
}

//String response with text/html; charset=UTF-8 Content type
func (c *C) String(status int, format string, val ...interface{}) {
	c.Writer.Header().Set(contentType, "text/html; charset=UTF-8")
	c.Writer.WriteHeader(status)
	if len(val) == 0 {
		c.Writer.Write([]byte(format))
	} else {
		c.Writer.Write([]byte(fmt.Sprintf(format, val...)))
	}
}

//Download response with application/octet-stream; charset=UTF-8 Content type
func (c *C) Download(status int, v []byte) {
	c.Writer.Header().Set(contentType, "application/octet-stream; charset=UTF-8")
	c.Writer.WriteHeader(status)
	c.Writer.Write(v)
}

//HTML render template engine
func (c *C) HTML(name string, data interface{}) {
	c.render.Render(c.Writer, name, data)
}

//ParseJSON decode json to interface{}
func (c *C) ParseJSON(v interface{}) error {
	return json.NewDecoder(c.Request.Body).Decode(v)
}

//HTTPLang get first language from HTTP Header
func (c *C) HTTPLang() string {
	langStr := c.Request.Header.Get(acceptLanguage)
	return strings.Split(langStr, ",")[0]
}

//Redirect 302 response
func (c *C) Redirect(url string) {
	http.Redirect(c.Writer, c.Request, url, 302)
}

//Stop call maddileware
func (c *C) Abort() {
	c.index = abortIndex
}

func (c *C) AbortWithStatus(status int) {
	c.Writer.WriteHeader(status)
	c.Abort()
}

func (c *C) Error(err error) {
	c.err = err
	c.errorHandlerFunc(c, err)
	c.index = abortIndex
}

func (c *C) GetError() error {
	return c.err
}

//Next next middleware
func (c *C) Next() {
	c.index++
	s := int8(len(c.handlers))
	if c.index < s {
		c.handlers[c.index](c)
	}
}

//ClientIP get ip from RemoteAddr
func (c *C) ClientIP() string {
	return c.Request.RemoteAddr
}

//Set context
func (c *C) Set(key string, v interface{}) {
	if c.context == nil {
		c.context = make(map[string]interface{})
	}
	c.context[key] = v
}

//Get context
func (c *C) Get(key string) interface{} {
	return c.context[key]
}
<commit_msg>add GetContext method<commit_after>package ace

import (
	"encoding/json"
	"fmt"
	"github.com/julienschmidt/httprouter"
	"math"
	"net/http"
	"strings"
)

const (
	contentType    = "Content-Type"
	acceptLanguage = "Accept-Language"
	abortIndex     = math.MaxInt8 / 2
)

//C is context for every goroutine
type C struct {
	writercache      responseWriter
	Params           httprouter.Params
	Request          *http.Request
	Writer           ResponseWriter
	index            int8
	handlers         []HandlerFunc
	errorHandlerFunc ErrorHandlerFunc
	//recovery
	context map[string]interface{}
	err     error
	Session *session
	render  Renderer
}

func (a *Ace) CreateContext(w http.ResponseWriter, r *http.Request) *C {
	c := a.pool.Get().(*C)
	c.writercache.reset(w)
	c.Request = r
	c.context = nil
	c.index = -1
	c.render = a.render

	return c
}

//JSON response with application/json; charset=UTF-8 Content type
func (c *C) JSON(status int, v interface{}) {
	result, err := json.Marshal(v)
	if err != nil {
		panic(err)
	}

	c.Writer.Header().Set(contentType, "application/json; charset=UTF-8")
	c.Writer.WriteHeader(status)
	c.Writer.Write(result)
}

//String response with text/html; charset=UTF-8 Content type
func (c *C) String(status int, format string, val ...interface{}) {
	c.Writer.Header().Set(contentType, "text/html; charset=UTF-8")
	c.Writer.WriteHeader(status)
	if len(val) == 0 {
		c.Writer.Write([]byte(format))
	} else {
		c.Writer.Write([]byte(fmt.Sprintf(format, val...)))
	}
}

//Download response with application/octet-stream; charset=UTF-8 Content type
func (c *C) Download(status int, v []byte) {
	c.Writer.Header().Set(contentType, "application/octet-stream; charset=UTF-8")
	c.Writer.WriteHeader(status)
	c.Writer.Write(v)
}

//HTML render template engine
func (c *C) HTML(name string, data interface{}) {
	c.render.Render(c.Writer, name, data)
}

//ParseJSON decode json to interface{}
func (c *C) ParseJSON(v interface{}) error {
	return json.NewDecoder(c.Request.Body).Decode(v)
}

//HTTPLang get first language from HTTP Header
func (c *C) HTTPLang() string {
	langStr := c.Request.Header.Get(acceptLanguage)
	return strings.Split(langStr, ",")[0]
}

//Redirect 302 response
func (c *C) Redirect(url string) {
	http.Redirect(c.Writer, c.Request, url, 302)
}

//Stop call maddileware
func (c *C) Abort() {
	c.index = abortIndex
}

func (c *C) AbortWithStatus(status int) {
	c.Writer.WriteHeader(status)
	c.Abort()
}

func (c *C) Error(err error) {
	c.err = err
	c.errorHandlerFunc(c, err)
	c.index = abortIndex
}

func (c *C) GetError() error {
	return c.err
}

//Next next middleware
func (c *C) Next() {
	c.index++
	s := int8(len(c.handlers))
	if c.index < s {
		c.handlers[c.index](c)
	}
}

//ClientIP get ip from RemoteAddr
func (c *C) ClientIP() string {
	return c.Request.RemoteAddr
}

//Set context
func (c *C) Set(key string, v interface{}) {
	if c.context == nil {
		c.context = make(map[string]interface{})
	}
	c.context[key] = v
}

//Get context
func (c *C) Get(key string) interface{} {
	return c.context[key]
}

func (c *C) GetContext() map[string]interface{} {
	return c.context
}
<|endoftext|>


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

package collateral

import (
	"bytes"
	"fmt"
	"html"
	"os"
	"sort"
	"strconv"
	"strings"

	"github.com/spf13/cobra"
	"github.com/spf13/cobra/doc"
	"github.com/spf13/pflag"
)

// Control determines the behavior of the EmitCollateral function
type Control struct {
	// OutputDir specifies the directory to output the collateral files
	OutputDir string

	// EmitManPages controls whether to produce man pages.
	EmitManPages bool

	// EmitYAML controls whether to produce YAML files.
	EmitYAML bool

	// EmitBashCompletion controls whether to produce bash completion files.
	EmitBashCompletion bool

	// EmitMarkdown controls whether to produce markdown documentation files.
	EmitMarkdown bool

	// EmitHTMLFragmentWithFrontMatter controls whether to produce HTML fragments with Jekyll/Hugo front matter.
	EmitHTMLFragmentWithFrontMatter bool

	// ManPageInfo provides extra information necessary when emitting man pages.
	ManPageInfo doc.GenManHeader
}

// EmitCollateral produces a set of collateral files for a CLI command. You can
// select to emit markdown to describe a command's function, man pages, YAML
// descriptions, and bash completion files.
func EmitCollateral(root *cobra.Command, c *Control) error {
	if c.EmitManPages {
		if err := doc.GenManTree(root, &c.ManPageInfo, c.OutputDir); err != nil {
			return fmt.Errorf("unable to output manpage tree: %v", err)
		}
	}

	if c.EmitMarkdown {
		if err := doc.GenMarkdownTree(root, c.OutputDir); err != nil {
			return fmt.Errorf("unable to output markdown tree: %v", err)
		}
	}

	if c.EmitHTMLFragmentWithFrontMatter {
		if err := genHTMLFragment(root, c.OutputDir+"/"+root.Name()+".html"); err != nil {
			return fmt.Errorf("unable to output HTML fragment file: %v", err)
		}
	}

	if c.EmitYAML {
		if err := doc.GenYamlTree(root, c.OutputDir); err != nil {
			return fmt.Errorf("unable to output YAML tree: %v", err)
		}
	}

	if c.EmitBashCompletion {
		if err := root.GenBashCompletionFile(c.OutputDir + "/" + root.Name() + ".bash"); err != nil {
			return fmt.Errorf("unable to output bash completion file: %v", err)
		}
	}

	return nil
}

type generator struct {
	buffer *bytes.Buffer
}

func (g *generator) emit(str ...string) {
	for _, s := range str {
		g.buffer.WriteString(s)
	}
	g.buffer.WriteByte('\n')
}

func findCommands(commands map[string]*cobra.Command, cmd *cobra.Command) {
	cmd.InitDefaultHelpCmd()
	cmd.InitDefaultHelpFlag()

	commands[cmd.CommandPath()] = cmd
	for _, c := range cmd.Commands() {
		findCommands(commands, c)
	}
}

const help = "help"

func genHTMLFragment(cmd *cobra.Command, path string) error {
	commands := make(map[string]*cobra.Command)
	findCommands(commands, cmd)

	names := make([]string, len(commands))
	i := 0
	for n := range commands {
		names[i] = n
		i++
	}
	sort.Strings(names)

	g := &generator{
		buffer: &bytes.Buffer{},
	}

	count := 0
	for _, n := range names {
		if commands[n].Name() == help {
			continue
		}

		count++
	}

	g.genFileHeader(cmd, count)
	for _, n := range names {
		if commands[n].Name() == help {
			continue
		}

		g.genCommand(commands[n])
	}

	f, err := os.Create(path)
	if err != nil {
		return err
	}
	_, err = g.buffer.WriteTo(f)
	_ = f.Close()

	return err
}

func (g *generator) genFileHeader(root *cobra.Command, numEntries int) {
	g.emit("---")
	g.emit("title: ", root.Name())
	g.emit("description: ", root.Short)
	g.emit("generator: pkg-collateral-docs")
	g.emit("number_of_entries: ", strconv.Itoa(numEntries))
	g.emit("---")
}

func (g *generator) genCommand(cmd *cobra.Command) {
	if cmd.Hidden || cmd.Deprecated != "" {
		return
	}

	if cmd.HasParent() {
		g.emit("
", cmd.CommandPath(), "
")
	}

	if cmd.Long != "" {
		g.emitText(cmd.Long)
	} else if cmd.Short != "" {
		g.emitText(cmd.Short)
	}

	if cmd.Runnable() {
		g.emit("
", html.EscapeString(cmd.UseLine()))
		g.emit("
")
	}

	// TODO: output aliases

	flags := cmd.NonInheritedFlags()
	flags.SetOutput(g.buffer)

	parentFlags := cmd.InheritedFlags()
	parentFlags.SetOutput(g.buffer)

	if flags.HasFlags() || parentFlags.HasFlags() {
		f := make(map[string]*pflag.Flag)
		addFlags(f, flags)
		addFlags(f, parentFlags)

		if len(f) > 0 {
			names := make([]string, len(f))
			i := 0
			for n := range f {
				names[i] = n
				i++
			}
			sort.Strings(names)

			genShorthand := false
			for _, v := range f {
				if v.Shorthand != "" && v.ShorthandDeprecated == "" {
					genShorthand = true
					break
				}
			}

			g.emit("
")
			g.emit("
")
			g.emit("Flags	")
			if genShorthand {
				g.emit("Shorthand	")
			}
			g.emit("Description	")
			g.emit("
")
			g.emit("
")

			for _, n := range names {
				g.genFlag(f[n], genShorthand)
			}

			g.emit("
")
			g.emit("
")
		}
	}

	if len(cmd.Example) > 0 {
		g.emit("
", "Examples", "
")
		g.emit("
", html.EscapeString(cmd.Example))
		g.emit("
")
	}
}

func addFlags(f map[string]*pflag.Flag, s *pflag.FlagSet) {
	s.VisitAll(func(flag *pflag.Flag) {
		if flag.Deprecated != "" || flag.Hidden {
			return
		}

		if flag.Name == help {
			return
		}

		f[flag.Name] = flag
	})
}

func (g *generator) genFlag(flag *pflag.Flag, genShorthand bool) {
	varname, usage := unquoteUsage(flag)
	if varname != "" {
		varname = " <" + varname + ">"
	}

	def := ""
	if flag.Value.Type() == "string" {
		def = fmt.Sprintf(" (default `%s`)", flag.DefValue)
	} else if flag.Value.Type() != "bool" {
		def = fmt.Sprintf(" (default `%s`)", flag.DefValue)
	}

	g.emit("
")
	g.emit("", "--", flag.Name, html.EscapeString(varname), "	")

	if genShorthand {
		if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {
			g.emit("", "-", flag.Shorthand, "	")
		} else {
			g.emit("	")
		}
	}

	g.emit("", html.EscapeString(usage), " ", def, "	")
	g.emit("
")
}

func (g *generator) emitText(text string) {
	paras := strings.Split(text, "\n\n")
	for _, p := range paras {
		g.emit("
", html.EscapeString(p), "
")
	}
}

// unquoteUsage extracts a back-quoted name from the usage
// string for a flag and returns it and the un-quoted usage.
// Given "a `name` to show" it returns ("name", "a name to show").
// If there are no back quotes, the name is an educated guess of the
// type of the flag's value, or the empty string if the flag is boolean.
func unquoteUsage(flag *pflag.Flag) (name string, usage string) {
	// Look for a back-quoted name, but avoid the strings package.
	usage = flag.Usage
	for i := 0; i < len(usage); i++ {
		if usage[i] == '`' {
			for j := i + 1; j < len(usage); j++ {
				if usage[j] == '`' {
					name = usage[i+1 : j]
					usage = usage[:i] + name + usage[j+1:]
					return name, usage
				}
			}
			break // Only one back quote; use type name.
		}
	}

	name = flag.Value.Type()
	switch name {
	case "bool":
		name = ""
	case "float64":
		name = "float"
	case "int64":
		name = "int"
	case "uint64":
		name = "uint"
	}

	return
}

func normalizeID(id string) string {
	id = strings.Replace(id, " ", "-", -1)
	return strings.Replace(id, ".", "-", -1)
}
<commit_msg>output command alias (#8449)<commit_after>// Copyright 2018 Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package collateral

import (
	"bytes"
	"fmt"
	"html"
	"os"
	"sort"
	"strconv"
	"strings"

	"github.com/spf13/cobra"
	"github.com/spf13/cobra/doc"
	"github.com/spf13/pflag"
)

// Control determines the behavior of the EmitCollateral function
type Control struct {
	// OutputDir specifies the directory to output the collateral files
	OutputDir string

	// EmitManPages controls whether to produce man pages.
	EmitManPages bool

	// EmitYAML controls whether to produce YAML files.
	EmitYAML bool

	// EmitBashCompletion controls whether to produce bash completion files.
	EmitBashCompletion bool

	// EmitMarkdown controls whether to produce markdown documentation files.
	EmitMarkdown bool

	// EmitHTMLFragmentWithFrontMatter controls whether to produce HTML fragments with Jekyll/Hugo front matter.
	EmitHTMLFragmentWithFrontMatter bool

	// ManPageInfo provides extra information necessary when emitting man pages.
	ManPageInfo doc.GenManHeader
}

// EmitCollateral produces a set of collateral files for a CLI command. You can
// select to emit markdown to describe a command's function, man pages, YAML
// descriptions, and bash completion files.
func EmitCollateral(root *cobra.Command, c *Control) error {
	if c.EmitManPages {
		if err := doc.GenManTree(root, &c.ManPageInfo, c.OutputDir); err != nil {
			return fmt.Errorf("unable to output manpage tree: %v", err)
		}
	}

	if c.EmitMarkdown {
		if err := doc.GenMarkdownTree(root, c.OutputDir); err != nil {
			return fmt.Errorf("unable to output markdown tree: %v", err)
		}
	}

	if c.EmitHTMLFragmentWithFrontMatter {
		if err := genHTMLFragment(root, c.OutputDir+"/"+root.Name()+".html"); err != nil {
			return fmt.Errorf("unable to output HTML fragment file: %v", err)
		}
	}

	if c.EmitYAML {
		if err := doc.GenYamlTree(root, c.OutputDir); err != nil {
			return fmt.Errorf("unable to output YAML tree: %v", err)
		}
	}

	if c.EmitBashCompletion {
		if err := root.GenBashCompletionFile(c.OutputDir + "/" + root.Name() + ".bash"); err != nil {
			return fmt.Errorf("unable to output bash completion file: %v", err)
		}
	}

	return nil
}

type generator struct {
	buffer *bytes.Buffer
}

func (g *generator) emit(str ...string) {
	for _, s := range str {
		g.buffer.WriteString(s)
	}
	g.buffer.WriteByte('\n')
}

func findCommands(commands map[string]*cobra.Command, cmd *cobra.Command) {
	cmd.InitDefaultHelpCmd()
	cmd.InitDefaultHelpFlag()

	commands[cmd.CommandPath()] = cmd
	for _, c := range cmd.Commands() {
		findCommands(commands, c)
	}
}

const help = "help"

func genHTMLFragment(cmd *cobra.Command, path string) error {
	commands := make(map[string]*cobra.Command)
	findCommands(commands, cmd)

	names := make([]string, len(commands))
	i := 0
	for n := range commands {
		names[i] = n
		i++
	}
	sort.Strings(names)

	g := &generator{
		buffer: &bytes.Buffer{},
	}

	count := 0
	for _, n := range names {
		if commands[n].Name() == help {
			continue
		}

		count++
	}

	g.genFileHeader(cmd, count)
	for _, n := range names {
		if commands[n].Name() == help {
			continue
		}

		g.genCommand(commands[n])
	}

	f, err := os.Create(path)
	if err != nil {
		return err
	}
	_, err = g.buffer.WriteTo(f)
	_ = f.Close()

	return err
}

func (g *generator) genFileHeader(root *cobra.Command, numEntries int) {
	g.emit("---")
	g.emit("title: ", root.Name())
	g.emit("description: ", root.Short)
	g.emit("generator: pkg-collateral-docs")
	g.emit("number_of_entries: ", strconv.Itoa(numEntries))
	g.emit("---")
}

func (g *generator) genCommand(cmd *cobra.Command) {
	if cmd.Hidden || cmd.Deprecated != "" {
		return
	}

	if cmd.HasParent() {
		g.emit("
", cmd.CommandPath(), "
")
	}

	if cmd.Long != "" {
		g.emitText(cmd.Long)
	} else if cmd.Short != "" {
		g.emitText(cmd.Short)
	}

	if cmd.Runnable() {
		g.emit("
", html.EscapeString(cmd.UseLine()))
		g.emit("
")
	}

	if len(cmd.Aliases) > 0 {
		g.emit("
")
		g.emit(cmd.Aliases...)
		g.emit("
")
	}

	flags := cmd.NonInheritedFlags()
	flags.SetOutput(g.buffer)

	parentFlags := cmd.InheritedFlags()
	parentFlags.SetOutput(g.buffer)

	if flags.HasFlags() || parentFlags.HasFlags() {
		f := make(map[string]*pflag.Flag)
		addFlags(f, flags)
		addFlags(f, parentFlags)

		if len(f) > 0 {
			names := make([]string, len(f))
			i := 0
			for n := range f {
				names[i] = n
				i++
			}
			sort.Strings(names)

			genShorthand := false
			for _, v := range f {
				if v.Shorthand != "" && v.ShorthandDeprecated == "" {
					genShorthand = true
					break
				}
			}

			g.emit("
")
			g.emit("
")
			g.emit("Flags	")
			if genShorthand {
				g.emit("Shorthand	")
			}
			g.emit("Description	")
			g.emit("
")
			g.emit("
")

			for _, n := range names {
				g.genFlag(f[n], genShorthand)
			}

			g.emit("
")
			g.emit("
")
		}
	}

	if len(cmd.Example) > 0 {
		g.emit("
", "Examples", "
")
		g.emit("
", html.EscapeString(cmd.Example))
		g.emit("
")
	}
}

func addFlags(f map[string]*pflag.Flag, s *pflag.FlagSet) {
	s.VisitAll(func(flag *pflag.Flag) {
		if flag.Deprecated != "" || flag.Hidden {
			return
		}

		if flag.Name == help {
			return
		}

		f[flag.Name] = flag
	})
}

func (g *generator) genFlag(flag *pflag.Flag, genShorthand bool) {
	varname, usage := unquoteUsage(flag)
	if varname != "" {
		varname = " <" + varname + ">"
	}

	def := ""
	if flag.Value.Type() == "string" {
		def = fmt.Sprintf(" (default `%s`)", flag.DefValue)
	} else if flag.Value.Type() != "bool" {
		def = fmt.Sprintf(" (default `%s`)", flag.DefValue)
	}

	g.emit("
")
	g.emit("", "--", flag.Name, html.EscapeString(varname), "	")

	if genShorthand {
		if flag.Shorthand != "" && flag.ShorthandDeprecated == "" {
			g.emit("", "-", flag.Shorthand, "	")
		} else {
			g.emit("	")
		}
	}

	g.emit("", html.EscapeString(usage), " ", def, "	")
	g.emit("
")
}

func (g *generator) emitText(text string) {
	paras := strings.Split(text, "\n\n")
	for _, p := range paras {
		g.emit("
", html.EscapeString(p), "
")
	}
}

// unquoteUsage extracts a back-quoted name from the usage
// string for a flag and returns it and the un-quoted usage.
// Given "a `name` to show" it returns ("name", "a name to show").
// If there are no back quotes, the name is an educated guess of the
// type of the flag's value, or the empty string if the flag is boolean.
func unquoteUsage(flag *pflag.Flag) (name string, usage string) {
	// Look for a back-quoted name, but avoid the strings package.
	usage = flag.Usage
	for i := 0; i < len(usage); i++ {
		if usage[i] == '`' {
			for j := i + 1; j < len(usage); j++ {
				if usage[j] == '`' {
					name = usage[i+1 : j]
					usage = usage[:i] + name + usage[j+1:]
					return name, usage
				}
			}
			break // Only one back quote; use type name.
		}
	}

	name = flag.Value.Type()
	switch name {
	case "bool":
		name = ""
	case "float64":
		name = "float"
	case "int64":
		name = "int"
	case "uint64":
		name = "uint"
	}

	return
}

func normalizeID(id string) string {
	id = strings.Replace(id, " ", "-", -1)
	return strings.Replace(id, ".", "-", -1)
}
<|endoftext|>


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

package com

import (
	"fmt"
	"strconv"
)

// Convert string to specify type.
type StrTo string

func (f StrTo) Exist() bool {
	return string(f) != string(0x1E)
}

func (f StrTo) Uint8() (uint8, error) {
	v, err := strconv.ParseUint(f.String(), 10, 8)
	return uint8(v), err
}

func (f StrTo) Int() (int, error) {
	v, err := strconv.ParseInt(f.String(), 10, 0)
	return int(v), err
}

func (f StrTo) Int64() (int64, error) {
	v, err := strconv.ParseInt(f.String(), 10, 64)
	return int64(v), err
}

func (f StrTo) Float64() (float64, error) {
	v, err := strconv.ParseFloat(f.String(), 64)
	return float64(v), err
}

func (f StrTo) MustUint8() uint8 {
	v, _ := f.Uint8()
	return v
}

func (f StrTo) MustInt() int {
	v, _ := f.Int()
	return v
}

func (f StrTo) MustInt64() int64 {
	v, _ := f.Int64()
	return v
}

func (f StrTo) MustFloat64() float64 {
	v, _ := f.Float64()
	return v
}

func (f StrTo) String() string {
	if f.Exist() {
		return string(f)
	}
	return ""
}

// Convert any type to string.
func ToStr(value interface{}, args ...int) (s string) {
	switch v := value.(type) {
	case bool:
		s = strconv.FormatBool(v)
	case float32:
		s = strconv.FormatFloat(float64(v), 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 32))
	case float64:
		s = strconv.FormatFloat(v, 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 64))
	case int:
		s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
	case int8:
		s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
	case int16:
		s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
	case int32:
		s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
	case int64:
		s = strconv.FormatInt(v, argInt(args).Get(0, 10))
	case uint:
		s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
	case uint8:
		s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
	case uint16:
		s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
	case uint32:
		s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
	case uint64:
		s = strconv.FormatUint(v, argInt(args).Get(0, 10))
	case string:
		s = v
	case []byte:
		s = string(v)
	default:
		s = fmt.Sprintf("%v", v)
	}
	return s
}

type argInt []int

func (a argInt) Get(i int, args ...int) (r int) {
	if i >= 0 && i < len(a) {
		r = a[i]
	} else if len(args) > 0 {
		r = args[0]
	}
	return
}

// HexStr2int converts hex format string to decimal number.
func HexStr2int(hexStr string) (int, error) {
	num := 0
	length := len(hexStr)
	for i := 0; i < length; i++ {
		char := hexStr[length-i-1]
		factor := -1

		switch {
		case char >= '0' && char <= '9':
			factor = int(char) - '0'
		case char >= 'a' && char <= 'f':
			factor = int(char) - 'a' + 10
		default:
			return -1, fmt.Errorf("invalid hex: %s", string(char))
		}

		num += factor * PowInt(16, i)
	}
	return num, nil
}

// Int2HexStr converts decimal number to hex format string.
func Int2HexStr(num int) (hex string) {
	if num == 0 {
		return "0"
	}

	for num > 0 {
		r := num % 16

		c := "?"
		if r >= 0 && r <= 9 {
			c = string(r + '0')
		} else {
			c = string(r + 'a' - 10)
		}
		hex = c + hex
		num = num / 16
	}
	return hex
}
<commit_msg>Convert int to string using rune() (#29)<commit_after>// Copyright 2014 com authors
//
// Licensed under the Apache License, Version 2.0 (the "License"): you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.

package com

import (
	"fmt"
	"strconv"
)

// Convert string to specify type.
type StrTo string

func (f StrTo) Exist() bool {
	return string(f) != string(rune(0x1E))
}

func (f StrTo) Uint8() (uint8, error) {
	v, err := strconv.ParseUint(f.String(), 10, 8)
	return uint8(v), err
}

func (f StrTo) Int() (int, error) {
	v, err := strconv.ParseInt(f.String(), 10, 0)
	return int(v), err
}

func (f StrTo) Int64() (int64, error) {
	v, err := strconv.ParseInt(f.String(), 10, 64)
	return int64(v), err
}

func (f StrTo) Float64() (float64, error) {
	v, err := strconv.ParseFloat(f.String(), 64)
	return float64(v), err
}

func (f StrTo) MustUint8() uint8 {
	v, _ := f.Uint8()
	return v
}

func (f StrTo) MustInt() int {
	v, _ := f.Int()
	return v
}

func (f StrTo) MustInt64() int64 {
	v, _ := f.Int64()
	return v
}

func (f StrTo) MustFloat64() float64 {
	v, _ := f.Float64()
	return v
}

func (f StrTo) String() string {
	if f.Exist() {
		return string(f)
	}
	return ""
}

// Convert any type to string.
func ToStr(value interface{}, args ...int) (s string) {
	switch v := value.(type) {
	case bool:
		s = strconv.FormatBool(v)
	case float32:
		s = strconv.FormatFloat(float64(v), 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 32))
	case float64:
		s = strconv.FormatFloat(v, 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 64))
	case int:
		s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
	case int8:
		s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
	case int16:
		s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
	case int32:
		s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
	case int64:
		s = strconv.FormatInt(v, argInt(args).Get(0, 10))
	case uint:
		s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
	case uint8:
		s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
	case uint16:
		s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
	case uint32:
		s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
	case uint64:
		s = strconv.FormatUint(v, argInt(args).Get(0, 10))
	case string:
		s = v
	case []byte:
		s = string(v)
	default:
		s = fmt.Sprintf("%v", v)
	}
	return s
}

type argInt []int

func (a argInt) Get(i int, args ...int) (r int) {
	if i >= 0 && i < len(a) {
		r = a[i]
	} else if len(args) > 0 {
		r = args[0]
	}
	return
}

// HexStr2int converts hex format string to decimal number.
func HexStr2int(hexStr string) (int, error) {
	num := 0
	length := len(hexStr)
	for i := 0; i < length; i++ {
		char := hexStr[length-i-1]
		factor := -1

		switch {
		case char >= '0' && char <= '9':
			factor = int(char) - '0'
		case char >= 'a' && char <= 'f':
			factor = int(char) - 'a' + 10
		default:
			return -1, fmt.Errorf("invalid hex: %s", string(char))
		}

		num += factor * PowInt(16, i)
	}
	return num, nil
}

// Int2HexStr converts decimal number to hex format string.
func Int2HexStr(num int) (hex string) {
	if num == 0 {
		return "0"
	}

	for num > 0 {
		r := num % 16

		c := "?"
		if r >= 0 && r <= 9 {
			c = string(rune(r + '0'))
		} else {
			c = string(rune(r + 'a' - 10))
		}
		hex = c + hex
		num = num / 16
	}
	return hex
}
<|endoftext|>


<commit_before>package ircbot

//ActionFunc is the type of function used in Actioner
type ActionFunc func(b *IrcBot, m *IrcMsg)

//Actionner is the interface that object need to implement custom action for the bot
type Actioner interface {
	Command() []string
	Usage() string
	Do(b *IrcBot, m *IrcMsg)
}
<commit_msg>improve doc of Actioner<commit_after>package ircbot

//ActionFunc is the type of function used in Actioner
type ActionFunc func(b *IrcBot, m *IrcMsg)

//Actioner is the interface that objects need to implement custom action for the bot
type Actioner interface {
	// array of IRC or user command on which the action will be triggered (MSG)
	// example for IRC command: JOIN, PRIVMSG
	// example for user command: .myCmd
	Command() []string

	// used to display help about the action
	Usage() string

	// actual action done by the bot
	Do(b *IrcBot, m *IrcMsg)
}
<|endoftext|>


<commit_before>// Copyright 2012 Thomas Jager <mail@jager.no> All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Driver for ADAM-4000 series I/O Modules from Advantech

package adam4000

import (
	"bufio"
	"encoding/hex"
	"fmt"
	"strconv"
	"strings"
	"time"
)

func NewADAM4000(addr byte, rc *bufio.Reader, wc *bufio.Writer) *ADAM4000 {
	var a ADAM4000
	a.address = addr
	a.rc = rc
	a.wc = wc
	a.Value = make([]float64, 8)
	a.Retries = 2
	a.Timeout = 500 * time.Millisecond
	go a.startReader()
	return &a
}

func (a *ADAM4000) GetName() (string, error) {
	resp, err := a.comResF("$%02XM\r", a.address)
	if err != nil {
		return "", err
	}
	a.Name = strings.Trim(string(resp[3:]), "\r ")
	return a.Name, nil
}

func (a *ADAM4000) GetAllValue() ([]float64, error) {
	resp, err := a.comResF("#%02X\r", a.address)
	if err != nil {
		return nil, err
	}
	values := string(resp[1:])
	fmt.Printf("%d\n", len(values))
	if len(values) == 57 {
		a.Value[0], err = strconv.ParseFloat(values[0:7], 64)
		a.Value[1], err = strconv.ParseFloat(values[7:14], 64)
		a.Value[2], err = strconv.ParseFloat(values[14:21], 64)
		a.Value[3], err = strconv.ParseFloat(values[21:28], 64)
		a.Value[4], err = strconv.ParseFloat(values[28:35], 64)
		a.Value[5], err = strconv.ParseFloat(values[35:42], 64)
		a.Value[6], err = strconv.ParseFloat(values[42:49], 64)
		a.Value[7], err = strconv.ParseFloat(values[49:56], 64)
	} else {
		intvals := make([]int64, 8)
		intvals[0], err = strconv.ParseInt(values[0:4], 16, 64)
		intvals[1], err = strconv.ParseInt(values[4:8], 16, 64)
		intvals[2], err = strconv.ParseInt(values[8:12], 16, 64)
		intvals[3], err = strconv.ParseInt(values[12:16], 16, 64)
		intvals[4], err = strconv.ParseInt(values[16:20], 16, 64)
		intvals[5], err = strconv.ParseInt(values[20:24], 16, 64)
		intvals[6], err = strconv.ParseInt(values[24:28], 16, 64)
		intvals[7], err = strconv.ParseInt(values[28:32], 16, 64)
		a.Value[0] = float64(intvals[0])
		a.Value[1] = float64(intvals[1])
		a.Value[2] = float64(intvals[2])
		a.Value[3] = float64(intvals[3])
		a.Value[4] = float64(intvals[4])
		a.Value[5] = float64(intvals[5])
		a.Value[6] = float64(intvals[6])
		a.Value[7] = float64(intvals[7])
	}
	return a.Value, err
}

func (a *ADAM4000) GetChannelValue(n int) (float64, error) {
	resp, err := a.comResF("#%02X%d\r", a.address, n)
	if err != nil {
		return float64(0), err
	}
	values := string(resp[1:])
	if len(values) == 7 {
		a.Value[n], err = strconv.ParseFloat(values[0:7], 64)
	} else {
		intval, _ := strconv.ParseInt(values[0:4], 16, 64)
		a.Value[n] = float64(intval)
	}
	return a.Value[n], err
}

func (a *ADAM4000) GetVersion() (string, error) {
	resp, err := a.comResF("$%02XF\r", a.address)
	if err != nil {
		return "", err
	}
	a.Version = strings.Trim(string(resp[3:]), "\r ")
	return a.Version, nil
}

func (a *ADAM4000) SetChannelRange(channel int, rangec InputRangeCode) error {
	_, err := a.comResF("$%02X7C%dR%02X\r", a.address, channel, byte(rangec))
	if err != nil {
		return err
	}
	return nil
}

func (a *ADAM4000) GetChannelRange(channel int) (InputRangeCode, error) {
	resp, err := a.comResF("$%02X8C%d\r", a.address, channel)
	if err != nil {
		return 0, err
	}
	rangec := make([]byte, 1)
	hex.Decode(rangec, resp[6:8])
	return InputRangeCode(rangec[0]), nil
}

func (a *ADAM4000) SyncronizeRead() error {
	//Stub
	return nil
}

func (a *ADAM4000) SyncronizedValue() ([]float64, error) {
	//Stub
	return nil, nil
}

func (a *ADAM4000) GetConfig() error {
	resp, err := a.comResF("$%02X2\r", a.address)
	if err != nil {
		return err
	}

	addr := make([]byte, 1)
	typecode := make([]byte, 1)
	baud := make([]byte, 1)
	data := make([]byte, 1)

	hex.Decode(addr, resp[1:3])
	hex.Decode(typecode, resp[3:5])
	hex.Decode(baud, resp[5:7])
	hex.Decode(data, resp[7:9])

	a.Address = addr[0]
	a.InputRange = InputRangeCode(typecode[0])
	a.BaudRate = BaudRateCode(baud[0])
	fmt.Printf("%X\n", data)
	a.Integration_time = data[0]&byte(1<<7) > 0
	a.Checksum = data[0]&byte(1<<6) > 0
	a.DataFormat = DataFormatCode(data[0] & byte(2))
	if a.Address != a.address {
		fmt.Printf("Warning: Configured address (%d) differs from connected address (%d), in init mode?\n", a.Address, a.address)
	}
	return nil
}

func (a *ADAM4000) SetConfig() error {
	data := byte(a.DataFormat)
	if a.Integration_time {
		data |= byte(1 << 7)
	}
	if a.Checksum {
		data |= byte(1 << 6)
	}

	_, err := a.comResF("%%%02X%02X%02X%02X%02X\r", a.address, a.Address, byte(a.InputRange), byte(a.BaudRate), data)
	return err
}
<commit_msg>Decrease command timeout<commit_after>// Copyright 2012 Thomas Jager <mail@jager.no> All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Driver for ADAM-4000 series I/O Modules from Advantech

package adam4000

import (
	"bufio"
	"encoding/hex"
	"fmt"
	"strconv"
	"strings"
	"time"
)

func NewADAM4000(addr byte, rc *bufio.Reader, wc *bufio.Writer) *ADAM4000 {
	var a ADAM4000
	a.address = addr
	a.rc = rc
	a.wc = wc
	a.Value = make([]float64, 8)
	a.Retries = 2
        //Modules usually reply within 50ms. Logest command seems to be read analog channels. (90-110ms)
	a.Timeout = 250 * time.Millisecond
	go a.startReader()
	return &a
}

func (a *ADAM4000) GetName() (string, error) {
	resp, err := a.comResF("$%02XM\r", a.address)
	if err != nil {
		return "", err
	}
	a.Name = strings.Trim(string(resp[3:]), "\r ")
	return a.Name, nil
}

func (a *ADAM4000) GetAllValue() ([]float64, error) {
	resp, err := a.comResF("#%02X\r", a.address)
	if err != nil {
		return nil, err
	}
	values := string(resp[1:])
	fmt.Printf("%d\n", len(values))
	if len(values) == 57 {
		a.Value[0], err = strconv.ParseFloat(values[0:7], 64)
		a.Value[1], err = strconv.ParseFloat(values[7:14], 64)
		a.Value[2], err = strconv.ParseFloat(values[14:21], 64)
		a.Value[3], err = strconv.ParseFloat(values[21:28], 64)
		a.Value[4], err = strconv.ParseFloat(values[28:35], 64)
		a.Value[5], err = strconv.ParseFloat(values[35:42], 64)
		a.Value[6], err = strconv.ParseFloat(values[42:49], 64)
		a.Value[7], err = strconv.ParseFloat(values[49:56], 64)
	} else {
		intvals := make([]int64, 8)
		intvals[0], err = strconv.ParseInt(values[0:4], 16, 64)
		intvals[1], err = strconv.ParseInt(values[4:8], 16, 64)
		intvals[2], err = strconv.ParseInt(values[8:12], 16, 64)
		intvals[3], err = strconv.ParseInt(values[12:16], 16, 64)
		intvals[4], err = strconv.ParseInt(values[16:20], 16, 64)
		intvals[5], err = strconv.ParseInt(values[20:24], 16, 64)
		intvals[6], err = strconv.ParseInt(values[24:28], 16, 64)
		intvals[7], err = strconv.ParseInt(values[28:32], 16, 64)
		a.Value[0] = float64(intvals[0])
		a.Value[1] = float64(intvals[1])
		a.Value[2] = float64(intvals[2])
		a.Value[3] = float64(intvals[3])
		a.Value[4] = float64(intvals[4])
		a.Value[5] = float64(intvals[5])
		a.Value[6] = float64(intvals[6])
		a.Value[7] = float64(intvals[7])
	}
	return a.Value, err
}

func (a *ADAM4000) GetChannelValue(n int) (float64, error) {
	resp, err := a.comResF("#%02X%d\r", a.address, n)
	if err != nil {
		return float64(0), err
	}
	values := string(resp[1:])
	if len(values) == 7 {
		a.Value[n], err = strconv.ParseFloat(values[0:7], 64)
	} else {
		intval, _ := strconv.ParseInt(values[0:4], 16, 64)
		a.Value[n] = float64(intval)
	}
	return a.Value[n], err
}

func (a *ADAM4000) GetVersion() (string, error) {
	resp, err := a.comResF("$%02XF\r", a.address)
	if err != nil {
		return "", err
	}
	a.Version = strings.Trim(string(resp[3:]), "\r ")
	return a.Version, nil
}

func (a *ADAM4000) SetChannelRange(channel int, rangec InputRangeCode) error {
	_, err := a.comResF("$%02X7C%dR%02X\r", a.address, channel, byte(rangec))
	if err != nil {
		return err
	}
	return nil
}

func (a *ADAM4000) GetChannelRange(channel int) (InputRangeCode, error) {
	resp, err := a.comResF("$%02X8C%d\r", a.address, channel)
	if err != nil {
		return 0, err
	}
	rangec := make([]byte, 1)
	hex.Decode(rangec, resp[6:8])
	return InputRangeCode(rangec[0]), nil
}

func (a *ADAM4000) SyncronizeRead() error {
	//Stub
	return nil
}

func (a *ADAM4000) SyncronizedValue() ([]float64, error) {
	//Stub
	return nil, nil
}

func (a *ADAM4000) GetConfig() error {
	resp, err := a.comResF("$%02X2\r", a.address)
	if err != nil {
		return err
	}

	addr := make([]byte, 1)
	typecode := make([]byte, 1)
	baud := make([]byte, 1)
	data := make([]byte, 1)

	hex.Decode(addr, resp[1:3])
	hex.Decode(typecode, resp[3:5])
	hex.Decode(baud, resp[5:7])
	hex.Decode(data, resp[7:9])

	a.Address = addr[0]
	a.InputRange = InputRangeCode(typecode[0])
	a.BaudRate = BaudRateCode(baud[0])
	fmt.Printf("%X\n", data)
	a.Integration_time = data[0]&byte(1<<7) > 0
	a.Checksum = data[0]&byte(1<<6) > 0
	a.DataFormat = DataFormatCode(data[0] & byte(2))
	if a.Address != a.address {
		fmt.Printf("Warning: Configured address (%d) differs from connected address (%d), in init mode?\n", a.Address, a.address)
	}
	return nil
}

func (a *ADAM4000) SetConfig() error {
	data := byte(a.DataFormat)
	if a.Integration_time {
		data |= byte(1 << 7)
	}
	if a.Checksum {
		data |= byte(1 << 6)
	}

	_, err := a.comResF("%%%02X%02X%02X%02X%02X\r", a.address, a.Address, byte(a.InputRange), byte(a.BaudRate), data)
	return err
}
<|endoftext|>


<commit_before>package reference

import (
	"encoding/json"
	"fmt"
	"log"

	"github.com/bosssauce/ponzu/content"
	"github.com/bosssauce/ponzu/management/editor"
	"github.com/bosssauce/ponzu/system/db"
)

// Select returns the []byte of a <select> HTML element plus internal <options> with a label.
// IMPORTANT:
// The `fieldName` argument will cause a panic if it is not exactly the string
// form of the struct field that this editor input is representing
func Select(fieldName string, p interface{}, attrs map[string]string, contentType string) []byte {
	ct, ok := content.Types[contentType]
	if !ok {
		log.Println("Cannot reference an invalid content type:", contentType)
		return nil
	}

	// get a handle to the underlying interface type for decoding
	t := ct()

	fmt.Println(t)

	// // decode all content type from db into options map
	// // map["?type=<contentType>&id=<id>"]t.String()
	options := make(map[string]string)
	jj := db.ContentAll(contentType + "__sorted")

	for i := range jj {
		err := json.Unmarshal(jj[i], t)
		if err != nil {
			log.Println("Error decoding into reference handle:", contentType, err)
		}

		// make sure it is an Identifiable
		item, ok := t.(content.Identifiable)
		if !ok {
			log.Println("Cannot use type", contentType, "as a reference since it does not implement content.Identifiable")
			return nil
		}

		k := fmt.Sprintf("?type=%s&id=%d", contentType, item.ItemID())
		v := item.String()
		options[k] = v
	}

	return editor.Select(fieldName, p, attrs, options)
}
<commit_msg>testing fix for import cycle issue<commit_after><|endoftext|>