github.com/brycereitano/goa@v0.0.0-20170315073847-8ffa6c85e265/goagen/codegen/helpers.go (about)

     1  package codegen
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"os"
     7  	"path/filepath"
     8  	"strings"
     9  	"unicode"
    10  
    11  	"github.com/goadesign/goa/design"
    12  	"github.com/goadesign/goa/version"
    13  )
    14  
    15  // CheckVersion returns an error if the ver is empty, contains an incorrect value or
    16  // a version number that is not compatible with the version of this repo.
    17  func CheckVersion(ver string) error {
    18  	compat, err := version.Compatible(ver)
    19  	if err != nil {
    20  		return err
    21  	}
    22  	if !compat {
    23  		return fmt.Errorf("version mismatch: using goagen %s to generate code that compiles with goa %s",
    24  			ver, version.String())
    25  	}
    26  	return nil
    27  }
    28  
    29  // CommandLine return the command used to run this process.
    30  func CommandLine() string {
    31  	// We don't use the full path to the tool so that running goagen multiple times doesn't
    32  	// end up creating different command line comments (because of the temporary directory it
    33  	// runs in).
    34  	var param string
    35  
    36  	if len(os.Args) > 1 {
    37  		args := make([]string, len(os.Args)-1)
    38  		gopaths := filepath.SplitList(os.Getenv("GOPATH"))
    39  		for i, a := range os.Args[1:] {
    40  			for _, p := range gopaths {
    41  				if strings.Contains(a, p) {
    42  					args[i] = strings.Replace(a, p, "$(GOPATH)", -1)
    43  					break
    44  				}
    45  			}
    46  			if args[i] == "" {
    47  				args[i] = a
    48  			}
    49  		}
    50  		param = strings.Join(args, " ")
    51  	}
    52  	rawcmd := filepath.Base(os.Args[0])
    53  	// Remove possible .exe suffix to not create different ouptut just because
    54  	// you ran goagen on Windows.
    55  	rawcmd = strings.TrimSuffix(rawcmd, ".exe")
    56  
    57  	cmd := fmt.Sprintf("$ %s %s", rawcmd, param)
    58  	return strings.Replace(cmd, " --", "\n\t--", -1)
    59  }
    60  
    61  // Comment produces line comments by concatenating the given strings and producing 80 characters
    62  // long lines starting with "//"
    63  func Comment(elems ...string) string {
    64  	var lines []string
    65  	for _, e := range elems {
    66  		lines = append(lines, strings.Split(e, "\n")...)
    67  	}
    68  	var trimmed = make([]string, len(lines))
    69  	for i, l := range lines {
    70  		trimmed[i] = strings.TrimLeft(l, " \t")
    71  	}
    72  	t := strings.Join(trimmed, "\n")
    73  
    74  	return Indent(t, "// ")
    75  }
    76  
    77  // Indent inserts prefix at the beginning of each non-empty line of s. The
    78  // end-of-line marker is NL.
    79  func Indent(s, prefix string) string {
    80  	return string(IndentBytes([]byte(s), []byte(prefix)))
    81  }
    82  
    83  // IndentBytes inserts prefix at the beginning of each non-empty line of b.
    84  // The end-of-line marker is NL.
    85  func IndentBytes(b, prefix []byte) []byte {
    86  	var res []byte
    87  	bol := true
    88  	for _, c := range b {
    89  		if bol && c != '\n' {
    90  			res = append(res, prefix...)
    91  		}
    92  		res = append(res, c)
    93  		bol = c == '\n'
    94  	}
    95  	return res
    96  }
    97  
    98  // Tabs returns a string made of depth tab characters.
    99  func Tabs(depth int) string {
   100  	var tabs string
   101  	for i := 0; i < depth; i++ {
   102  		tabs += "\t"
   103  	}
   104  	//	return fmt.Sprintf("%d%s", depth, tabs)
   105  	return tabs
   106  }
   107  
   108  // Add adds two integers and returns the sum of the two.
   109  func Add(a, b int) int { return a + b }
   110  
   111  // CanonicalTemplate returns the resource URI template as a format string suitable for use in the
   112  // fmt.Printf function family.
   113  func CanonicalTemplate(r *design.ResourceDefinition) string {
   114  	return design.WildcardRegex.ReplaceAllLiteralString(r.URITemplate(), "/%v")
   115  }
   116  
   117  // CanonicalParams returns the list of parameter names needed to build the canonical href to the
   118  // resource. It returns nil if the resource does not have a canonical action.
   119  func CanonicalParams(r *design.ResourceDefinition) []string {
   120  	var params []string
   121  	if ca := r.CanonicalAction(); ca != nil {
   122  		if len(ca.Routes) > 0 {
   123  			params = ca.Routes[0].Params()
   124  		}
   125  		for i, p := range params {
   126  			params[i] = Goify(p, false)
   127  		}
   128  	}
   129  	return params
   130  }
   131  
   132  // Casing exceptions
   133  var toLower = map[string]string{"OAuth": "oauth"}
   134  
   135  // SnakeCase produces the snake_case version of the given CamelCase string.
   136  func SnakeCase(name string) string {
   137  	for u, l := range toLower {
   138  		name = strings.Replace(name, u, l, -1)
   139  	}
   140  	var b bytes.Buffer
   141  	var lastUnderscore bool
   142  	ln := len(name)
   143  	if ln == 0 {
   144  		return ""
   145  	}
   146  	b.WriteRune(unicode.ToLower(rune(name[0])))
   147  	for i := 1; i < ln; i++ {
   148  		r := rune(name[i])
   149  		nextIsLower := false
   150  		if i < ln-1 {
   151  			n := rune(name[i+1])
   152  			nextIsLower = unicode.IsLower(n) && unicode.IsLetter(n)
   153  		}
   154  		if unicode.IsUpper(r) {
   155  			if !lastUnderscore && nextIsLower {
   156  				b.WriteRune('_')
   157  				lastUnderscore = true
   158  			}
   159  			b.WriteRune(unicode.ToLower(r))
   160  		} else {
   161  			b.WriteRune(r)
   162  			lastUnderscore = false
   163  		}
   164  	}
   165  	return b.String()
   166  }
   167  
   168  // KebabCase produces the kebab-case version of the given CamelCase string.
   169  func KebabCase(name string) string {
   170  	name = SnakeCase(name)
   171  	return strings.Replace(name, "_", "-", -1)
   172  }