Skip to content

Commit

Permalink
Merge pull request #4 from tcnksm/add-option
Browse files Browse the repository at this point in the history
Add option
  • Loading branch information
tcnksm committed Jul 15, 2015
2 parents 390741b + a9aabc4 commit c73a607
Show file tree
Hide file tree
Showing 4 changed files with 245 additions and 223 deletions.
14 changes: 8 additions & 6 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
This is road map of `license`, what I'm doing for next release and planing for future relase.
If you have feature request, please open issues or send pull request.


## 0.1.2

- Add `-force` option
- **DONE**: Add `-author`, `-year`, `-email`, `-project` option
- Dockerfile to build binary and release it to Github Release
- test (for cache)

## 0.1.0

Before release
Expand All @@ -14,9 +22,3 @@ Before release
- **DONE**: Cache function
- **DONE**: Fix `-output` to set directory
- **DONE**: `go-latest`

## 0.1.1

- Add `-force` option
- Dockerfile to build binary and release it to Github Release
- test (for cache)
251 changes: 35 additions & 216 deletions cli.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
package main

import (
"bufio"
"bytes"
"flag"
"fmt"
"io"
"net/http"
"os"
"os/signal"
"path/filepath"
"strconv"
"strings"
"time"

"github.com/google/go-github/github"
"github.com/mitchellh/colorstring"
"github.com/mitchellh/go-homedir"
"github.com/olekukonko/tablewriter"
"github.com/tcnksm/go-gitconfig"
Expand All @@ -32,6 +29,9 @@ const (
// DefaultOutput is default output file name
DefaultOutput = "LICENSE"

// Default Values. If it's not changed, licence will ask them
DefaultValue = "*"

// Default value for user input
DoNothing = "(no replacement)"
)
Expand All @@ -47,7 +47,13 @@ type CLI struct {
func (cli *CLI) Run(args []string) int {

var (
output string
output string

optionYear string
optionAuthor string
optionEmail string
optionProject string

noCache bool
raw bool
)
Expand All @@ -63,6 +69,12 @@ func (cli *CLI) Run(args []string) int {
flags.BoolVar(&noCache, "no-cache", false, "")
flags.BoolVar(&raw, "raw", false, "")

// Replacement values
flags.StringVar(&optionYear, "year", DefaultValue, "")
flags.StringVar(&optionAuthor, "author", DefaultValue, "")
flags.StringVar(&optionEmail, "email", DefaultValue, "")
flags.StringVar(&optionProject, "project", DefaultValue, "")

flList := flags.Bool("list", false, "")
flChoose := flags.Bool("choose", false, "")

Expand Down Expand Up @@ -263,62 +275,35 @@ func (cli *CLI) Run(args []string) int {
if !raw {

// Replace year if needed
var year string
if optionYear != DefaultValue {
year = optionYear
} else {
year = strconv.Itoa(time.Now().Year())
}

yearFolders := findPlaceholders(body, yearKeys)
year := strconv.Itoa(time.Now().Year())
for _, f := range yearFolders {
fmt.Fprintf(cli.errStream, "----> Replace placeholder %q to %q in LICENSE body\n", f, year)
body = strings.Replace(body, f, year, -1)
}

// Repalce name if needed
nameFolders := findPlaceholders(body, nameKeys)
if len(nameFolders) > 0 {
// Retrieve default value from .gitconfig
defaultName, _ := gitconfig.GithubUser()
if len(defaultName) == 0 {
defaultName = DoNothing
}

// Ask or Confirm default value from user
ans, _ := cli.AskString("Input fullname of author", defaultName)
if ans != DoNothing {
for _, f := range nameFolders {
fmt.Fprintf(cli.errStream, "----> Replace placeholder %q to %q in LICENSE body\n", f, ans)
body = strings.Replace(body, f, ans, -1)
}
}
// Replace author name if needed
defaultAuthor, _ := gitconfig.GithubUser()
if len(defaultAuthor) == 0 {
defaultAuthor = DoNothing
}
cli.ReplacePlaceholder(body, nameKeys, "Input author name", defaultAuthor, optionAuthor)

// Repalce email if needed
emailFolders := findPlaceholders(body, emailKeys)
if len(emailFolders) > 0 {
// Retrieve default value from .gitconfig
defaultEmail, _ := gitconfig.Email()
if len(defaultEmail) == 0 {
defaultEmail = DoNothing
}
// Ask or Confirm default value from user
ans, _ := cli.AskString("Input email", defaultEmail)
if ans != DoNothing {
for _, f := range emailFolders {
fmt.Fprintf(cli.errStream, "----> Replace placeholder %q to %q in LICENSE body\n", f, ans)
body = strings.Replace(body, f, ans, -1)
}
}
// Replace email if needed
defaultEmail, _ := gitconfig.Email()
if len(defaultEmail) == 0 {
defaultEmail = DoNothing
}
cli.ReplacePlaceholder(body, nameKeys, "Input email", defaultEmail, optionEmail)

// Replace miscs.
miscFolders := findPlaceholders(body, miscKeys)
if len(miscFolders) > 0 {
for _, f := range miscFolders {
ans, _ := cli.AskString(fmt.Sprintf("Input %q", constructQuery(f)), DoNothing)
if ans == DoNothing {
continue
}
fmt.Fprintf(cli.errStream, "----> Replace placeholder %q to %q in LICENSE body\n", f, ans)
body = strings.Replace(body, f, ans, 1)
}
}
// Replace project name if needed
cli.ReplacePlaceholder(body, projectKeys, "Input project name", DoNothing, optionProject)
}

// Write LICENSE body to file
Expand All @@ -340,172 +325,6 @@ func (cli *CLI) Run(args []string) int {
return ExitCodeOK
}

// AskNumber asks user to choose number from 1 to max
func (cli CLI) AskNumber(max int, defaultNum int) (int, error) {

sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, os.Interrupt)
defer signal.Stop(sigCh)

result := make(chan int, 1)
go func() {
for {

fmt.Fprintf(cli.errStream, "Your choice? [default: %d] ", defaultNum)

var line string
if _, err := fmt.Fscanln(os.Stdin, &line); err != nil {
Debugf("Failed to scan stdin: %s", err.Error())
}

Debugf("Input: %q", line)

// Use Default value
if line == "" {
result <- defaultNum
break
}

// Convert string to int
n, err := strconv.Atoi(line)
if err != nil {
fmt.Fprintf(cli.errStream, " is not a valid choice. Choose by number.\n\n")
continue
}

// Check input is in range
if n < 1 || max < n {
fmt.Fprintf(cli.errStream, " is not a valid choice. Choose from 1 to %d\n\n", max)
continue
}

result <- n
break
}
}()

select {
case <-sigCh:
return -1, fmt.Errorf("interrupted")
case num := <-result:
return num, nil
}
}

// AskString asks user to input some string
func (cli CLI) AskString(query string, defaultStr string) (string, error) {

sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, os.Interrupt)
defer signal.Stop(sigCh)

result := make(chan string, 1)
go func() {
fmt.Fprintf(cli.errStream, "%s [default: %s] ", query, defaultStr)

// TODO when string includes blank ...
reader := bufio.NewReader(os.Stdin)
line, err := reader.ReadString('\n')
if err != nil {
Debugf("Failed to scan stdin: %s", err.Error())
}
Debugf("Input: %q", line)

// Use Default value
line = strings.TrimRight(line, "\n")
if line == "" {
result <- defaultStr
}

result <- line
}()

select {
case <-sigCh:
return "", fmt.Errorf("interrupted")
case str := <-result:
return str, nil
}
}

// Choose shows shows LICENSE description from http://choosealicense.com/
// And ask user to choose LICENSE. It returns key to fetch LICENSE file.
// If something is wrong, return error.
func (cli *CLI) Choose() (string, error) {
colorstring.Fprintf(cli.errStream, chooseText)

num, err := cli.AskNumber(4, 1)
if err != nil {
return "", err
}

// If user selects 3, should ask user GPL V2 or V3
if num == 3 {
var buf bytes.Buffer
buf.WriteString("\n")
buf.WriteString("Which version do you want?\n")
buf.WriteString(" 1) V2\n")
buf.WriteString(" 2) V3\n")
fmt.Fprintf(cli.errStream, buf.String())

num, err = cli.AskNumber(2, 1)
if err != nil {
return "", err
}
num += 4
}

var key string
switch num {
case 1:
key = "mit"
case 2:
key = "apache-2.0"
case 4:
key = ""
case 5:
key = "gpl-2.0"
case 6:
key = "gpl-3.0"
default:
// Should not reach here
panic("Invalid number")
}

return key, nil
}

var chooseText = `Choose LICENSE like http://choosealicense.com/
[blue]Choosing an OSS license doesn't need to be scary[reset]
Which of the following best describes your situation?
1) I want it simple and permissive.
The [red][bold]MIT License[reset] is a permissive license that is short and to the
point. It lets people do anything they want with your code as long as they
provide attribution back to you and don't hold you liable.
e.g., jQuery, Rails
2) I'm concerned about patents.
The [red][bold]Apache License[reset] (apache-2.0) is a permissive license similar to the MIT License,
but also provides an express grant of patent rights from contributors to users.
e.g., Apache, SVN, NuGet
3) I care about sharing improvements.
The [red][bold]GPL V2[reset] (gpl-2.0) or [red][bold]GPL V3[reset] (gpl-3.0) is a copyleft license that requires
anyone who distributes your code or a derivative work to make the source available under
the same terms. V3 is similar to V2, but further restricts use in hardware that forbids
software alterations.
e.g., Linux, Git, WordPress
4) I want more choices.
`

var helpText = `Usage: license [option] [KEY]
Generate LICENSE file. If you provide KEY, it will try to get LICENSE by
Expand Down
Loading

0 comments on commit c73a607

Please sign in to comment.