Giter VIP home page Giter VIP logo

survey's Issues

Input only returns string

So, although the write tests handle different answer types, when you go up a level to the ask / askOne functions, they will always fail if you do a simple Input{} prompt with anything but a string.

given this test code:

func TestInt(t *testing.T) {
	q := []*Question{
		{
			Name: "age",
			Prompt: &Input{
				Message: "What is your age?",
			},
			Validate: Required,
		},
	}

	in, _ := ioutil.TempFile("", "")
	defer in.Close()

	os.Stdin = in

	io.WriteString(in, "21\n")
	in.Seek(0, os.SEEK_SET)

	ans := int64(0)

	err := Ask(q, &ans)

	assert.Nil(t, err)
	assert.Equal(t, int64(21), ans)

}

you'll always get an error "reflect.Set: value of type string is not assignable to type int64"
I believe it's due to the fact that Input.Prompt always converts stuff to strings at the end:

// we're done
	return string(line), err

So essentially, if you use Input you always have to expect a string back, unless i'm missing something.

Document where answers can be written to

I've been collecting answers to survey.MultiSelect etc. prompts into a []string. But from the source code it looks like it's possible to use structs/maps too?

func WriteAnswer(t interface{}, name string, v interface{}) (err error) {

If that's the case, Ask/AskOne methods that visibly accept t interface{} should probably document this behavior what t's type should/can be.

Input prompt on Answer renders wrong if answer is ""

Creating issue for problem I saw working on #55. The template has:

{{- if .Answer}}
  {{- color "cyan"}}{{.Answer}}{{color "reset"}}{{"\n"}}

So if the default answer is "" then it evaluates to false and the template shows the prompt again. We probbaly need a .ShowAnswer boolean flag for the template to know when we need to show an answer for a value that will be evaluated to false by text/template.

ANSI codes not respected by SecureCRT

When i use exapmple code
`package main

import (
"fmt"
"gopkg.in/AlecAivazis/survey.v1"
)

// the questions to ask
var qs = []*survey.Question{
{
Name: "name",
Prompt: &survey.Input{Message: "What is your name?"},
Validate: survey.Required,
},
{
Name: "color",
Prompt: &survey.Select{
Message: "Choose a color:",
Options: []string{"red", "blue", "green"},
Default: "red",
},
},
}

func main() {
// the answers will be written to this struct
answers := struct {
Name string // survey will match the question and field names
FavoriteColor string survey:"color" // or you can tag fields to match a specific name
}{}

// perform the questions
err := survey.Ask(qs, &answers)
if err != nil {
    fmt.Println(err.Error())
    return
}

fmt.Printf("%s chose %s.", answers.Name, answers.FavoriteColor)

}`

the menu is

[root@localhost]/home/mygo/src/cloudcon# go run c.go ? What is your name? 12 ? What is your name? 12 ? Choose a color: ❯ red blue green ? Choose a color: red ❯ blue green ? Choose a color: red blue ❯ green ? Choose a color: red blue ❯ green ? Choose a color: red blue ❯ green

Use more compatible symbols by default

The default customization option values, while nice looking, are not extraordinarily compatible with the average user's font face. This is especially relevant for a library like survey. Which will probably be used in applications which interact with less technical users.

It would be nice if survey shipped with some more compatible defaults:

core.ErrorIcon = "X"
core.HelpIcon = "????"
core.QuestionIcon = "?"
core.SelectFocusIcon = ">"
core.MarkedOptionIcon = "[x]"
core.UnmarkedOptionIcon = "[ ]"

They still end up looking pretty nice looking:

2017-09-07-150747_1920x1080_scrot

Choice questions with less than 3 options leave first line

Neat little package, thanks!

Unfortunately, when choice questions have just 1 or 2 options, the first line remains:

package main

import (
    "fmt"
    "github.com/alecaivazis/survey"
)

// the questions to ask
var qs = []*survey.Question{
    {
        Name: "color",
        Prompt: &survey.Choice{
            Message: "Choose a color:",
            Choices: []string{"red", "blue"},
            Default: "red",
        },
    },
}

func main() {
    answers, err := survey.Ask(qs)

    if err != nil {
        fmt.Println("\n", err.Error())
        return
    }

    fmt.Printf("%s chose %s.", answers["name"], answers["color"])
}

Prints, at the end:

? Choose a color:
? Choose a color: red
 chose red.

Help field for inputs does not seem to be working

Getting an error of 'unknown field 'Help' in struct literal of type survey.Input' when running something like this:

Prompt: &survey.Input{
			Message: "What is the site domain?",
			Help:    "The site name DOES contain the TLD (like '.com')",
		},

MultiSelect scrolling not obvious

When I presented a MultiSelect with a long list it's not clear to the user whether there are more items beyond Item 6 (there is 100 more items).

image

Inquirer.js communicates this better as they print a gray (Move up and down to reveal more choices) line at the bottom:

image

I see there's an empty line at the end of MultiSelect in survey package currently. Did you mean to add this note and forget about it perhaps?

Fix correct versioning of releases

Currently, some releases are incorrectly tagged in GitHub (missing the v prefix before e.g. 1.3.1):

skarmavbild 2017-09-29 kl 18 56 02

This causes gopkg to not pick up these versions:

skarmavbild 2017-09-29 kl 18 57 40

Which means that if you use github.com/AlecAivazis/survey you get build errors, and if you use gopkg.in/AlecAivazis/survey.v1/survey you get an older version without e.g. survey.Editor ¯_(ツ)_/¯

skarmavbild 2017-09-29 kl 18 53 57

Allow users to set output stream

It users like this library is printing interactive dialogues to stdout. This is making it difficult to write programs that prompt questions, which then prints something to stdout users can redirect to a file and use.

e.g. A program like

keyutil generate --to-file=- | jq .

Would print to stdout, which then would be consumed by the next program in the pipeline. However currently all questions go to stdout, making this impossible.

gokpg.in version uses github/.../core instead of gopkg.in/.../core

Hi,

I'm hope I'm not holding it wrong, but I just ran into the following issue which took me some time to debug. Following https://github.com/AlecAivazis/survey#customizing-output, I tried the following:

package main

import (
	surveyCore "gopkg.in/AlecAivazis/survey.v1/core"
	"gopkg.in/AlecAivazis/survey.v1"
)

func main() {
	surveyCore.QuestionIcon = "???"

	options := []string{"Chicken", "Egg"}
	var ret string
	prompt := &survey.Select{
		Message: "Which came first, the chicken or the egg?",
		Options: options,
	}
	survey.AskOne(prompt, &ret, nil)
}

However, that does not change the question icon. After some debugging, I found that I need to reference the GitHub package to get it work:

diff --git a/icon.go b/icon_fixed.go
index b94e586..8e09228 100644
--- a/icon.go
+++ b/icon_fixed.go
@@ -1,8 +1,8 @@
 package main

 import (
+       surveyCore "github.com/AlecAivazis/survey/core"
        "gopkg.in/AlecAivazis/survey.v1"
-       surveyCore "gopkg.in/AlecAivazis/survey.v1/core"
 )

 func main() {

Without being a Go expert, this seems wrong as it effectively breaks semantic versioning?

Thanks for the fantastic project!

Provide more examples, for all question types

I was trying to use MultiSelect and tried to look for code examples, mostly because it's unclear to me how I'm supposed to collect the answers back (what interface{}'s actual type should be).

I tried []string, didn't work. So I had to dig into examples/longlist.go, where I saw a survey.Select example. Apparently it deserializes into a struct that has a field that has the same name as question.Name. This sounds fine.

But I have to guess whether that field should be []int or []string because it's not documented at https://godoc.org/github.com/AlecAivazis/survey#MultiSelect and I can't find any examples. It seems like there's a little bit of friction or docs/examples gap.

Adding further questions after a select is breaking the package.

Putting further questions after a select question does not operate properly.

I will include a slightly modified version of your example/simple.go, where all I did was switch the order of the questions, so you can run it and see:

package main

import (
	"fmt"

	"github.com/AlecAivazis/survey"
)

// the questions to ask
var simpleQs = []*survey.Question{
	{
		Name: "color",
		Prompt: &survey.Select{
			Message: "Choose a color:",
			Options: []string{"red", "blue", "green"},
		},
		Validate: survey.Required,
	},
	{
		Name: "name",
		Prompt: &survey.Input{
			Message: "What is your name?",
		},
		Validate: survey.Required,
	},
}

func main() {
	answers := struct {
		Color string
		Name  string
	}{}
	// ask the question
	err := survey.Ask(simpleQs, &answers)

	if err != nil {
		fmt.Println(err.Error())
		return
	}
	// print the answers
	fmt.Printf("%s chose %s.\n", answers.Name, answers.Color)
}

If the format of the questions is incorrect, please inform on the correct way as the ReadMe seems to have two different ways to do it. One in the large example near the beginning, and one in the smaller examples below.

Thank you in advance for your help!

Tab-completion on file paths for input

I realize this might be super challenging, but one of the things I have in my cli app using survey is a place for users to enter the path to a local file. Tab-completion of the path would be super great. Has anyone taken a whack at this?

confirm and input prompts not working on windows

copying from discussion started in #51.

I ran go run tests\confirm.go and saw:

Enter 'yes'
? yes: (y/N) 
             ? yes: Yes
Answered true.
---------------------
Enter 'no'
? yes: (y/N)
             ? yes: No
Answered false.
---------------------

Select/Multiselect seems to work, but the recent changes to deal with the Help prompt rewriting seems to have broken the input and confirm prompts on windows.

Using cmd.exe on Window 10.

Is there a way to pass a different value on a Select prompt?

I have a Select prompt, and would like to display one thing to the user, but return a different value than what is being displayed.

That is to say, it will show "George Bluth", but would like it to instead return the value of "george-bluth", which is something i could have in a map, let's say.

In this particular case, I can transform the value myself (since it's simple toLower and string replacement), but in other cases it might be more arbitrary.

Conditionally prevent signals trapping

It seems that a simple survey like this:

ans := false
prompt := &survey.Confirm{
	Message: prompt_message,
}
survey.AskOne(prompt, &ans, nil)

is overriding SIGINT action, preventing my own application to apply its own trapping procedure.
Actually don't know if it's the way it's supposed to work, but in this case I need a way to prevent it to move that way.

two selects in a row don't save correct value

If you have two select blocks in a row and on the second selection you choose the first option without moving your cursor at all, it will save the value from the first selection block instead.

var simpleQs = []*survey.Question{
	{
		Name: "color",
		Prompt: &survey.Select{
			Message: "Choose a color:",
			Options: []string{"red", "blue", "green"},
		},
		Validate: survey.Required,
	},
	{
		Name: "color2",
		Prompt: &survey.Select{
			Message: "Choose a color:",
			Options: []string{"red", "blue", "green"},
		},
		Validate: survey.Required,
	},
}

func main() {
	answers := struct {
		Color  string
		Color2 string
	}{}
	// ask the question
	err := survey.Ask(simpleQs, &answers)

	if err != nil {
		fmt.Println(err.Error())
		return
	}
	// print the answers
	fmt.Printf("%s and %s.\n", answers.Color, answers.Color2)
}

In that example, if you select "blue" and then "red" the expected output is "blue and red" and the actual output is "blue and blue".

automated regression testing with expect

Hey @AlecAivazis, I continue to think about how to best use the files in your tests directory. I think expect is probably the way to go.

I think the easiest thing to do is use autoexpect which will automatically generate an expect script based on watching you interact with a program. For example I ran it on ask.go like:

$ autoexpect -f ask.exp go run ask.go
autoexpect started, file is ask.exp
Asking many.
? What is your name? Larry Bird
? Choose a color: blue
? What is your name? Larry Wall
Answered with Larry Wall.
Asking one with validation.
✘ Sorry, your reply was invalid: Value is required
? What is your name? Larry King
Answered with Larry King.
autoexpect done, file is ask.exp

It automatically captured all the input and output for that process and turned it into a script that can be directly executed to recreate that exact sequence. So if you run it the output will be the same:

$ ./ask.exp
spawn go run ask.go
Asking many.
? What is your name? Larry Bird
? Choose a color: blue
? What is your name? Larry Wall
Answered with Larry Wall.
Asking one with validation.
✘ Sorry, your reply was invalid: Value is required
? What is your name? Larry King
Answered with Larry King.

The ask.exp script that was generated will have all the output captured, even all the CSI codes.

Here is a useful snippet of ask.exp:

expect -exact "Asking many.\r
^[\[2K^[\[1;92m? ^[\[0m^[\[1;99mWhat is your name? ^[\[0m^[\[37m(Johnny Appleseed) ^[\[0m"
send -- "Larry Bird\r"
expect -exact "Larry Bird\r
^[\[1A^[\[2K^[\[1;92m? ^[\[0m^[\[1;99mWhat is your name? ^[\[0m^[\[36mLarry Bird^[\[0m\r
^[\[2K^[\[1;92m? ^[\[0m^[\[1;99mChoose a color:^[\[0m\r
^[\[1;99m  red^[\[0m\r
^[\[1;99m  blue^[\[0m\r
^[\[1;99m  green^[\[0m\r
^[\[1;36m> yellow^[\[0m\r
^[\[?25l^[\[2K^[\[1F^[\[2K^[\[1F^[\[2K^[\[1F^[\[2K^[\[1F^[\[2K^[\[1F^[\[2K^[\[1;92m? ^[\[0m^[\[1;99mChoose a color:^[\[0m\r
^[\[1;99m  red^[\[0m\r
^[\[1;99m  blue^[\[0m\r
^[\[1;99m  green^[\[0m\r
^[\[1;36m> yellow^[\[0m\r
"

Here we can see that I answered Larry Bird (the send) for the first name prompt, then the tty echo's that name back, then the prompt is rewritten with the name (Answer) colored in, followed by the "Choose a color" prompt (twice because Select.OnChange is called automatically with nil list on readline.SetConfig)

It might be useful if you want to just generate autoexpect scripts for each of these tests for the input you have been using to test with. Then we can just run them in a quick loop to make sure they all execute without error for a quick and easy regression test.

Not sure what platform, but if you use OSX you can easily install with brew install expect (which comes with autoexpect).

[bugs] validation.go run error

golang version 18
MacOS 10.12.4

$ go run examples/validation.go

command-line-arguments

examples/validation.go:13: cannot use "What is your name?" (type string) as type core.Renderer in field value
examples/validation.go:13: too few values in struct initializer
examples/validation.go:18: cannot use "Enter 'foo':" (type string) as type core.Renderer in field value
examples/validation.go:18: too few values in struct initializer

MultiSelect does not support cycling through the list

If I hit Up key at the beginning of the list, it should go to the item at the end of the list.

Similarly, if I hit Down at the end of the list, it should cycle back to the item at the beginning of the list.

This behavior is supported by Inquirer.js.

Answers can only be one word

Sorry for the flood of issues. Having a lot of fun with this lib though. 😄

Using the demo in the README, it seems that the survey.Input prompt truncates answers to just the first word. (Try using something like "hello dolly" as the answer.)

I'm on a roll with something, or I'd submit a patch right now -- maybe sometime in the future if you can't get around to it, however I'm not super familiar with terminal-fu.

A simple way to ask one question at a time

I have a situation where a fair amount of logic needs to happen between each question, and it would be good to be able to do something like this:

answer, err = survey.AskOne(&survey.Choice{
	Message: "...",
	Choices: []string{"..."},
})

What do you think?

Add support for MultiValue prompts

This is slightly different than multi-select in that it can be used to gather things like "tags".
e.g.:
? enter a tag:
user enters: "golang"
? add another (y/n)
user enters "y"
? enter a tag:
user enters "github"
? add another (y/n)
user enters "n"
... move on to next question

failed validation does not cleanup prompt on answer

I noticed while testing that if you fail a validation multiple times it will stack up the error messages. So this test code:

    answer := ""
    survey.AskOne(
        &survey.Input{Message: "Enter something:"},
        &answer,
        survey.Required,
    )
    fmt.Printf("response string: %s\n", answer)

Will produce this if you just type Enter a few times:

✘ Sorry, your reply was invalid: Value is required
✘ Sorry, your reply was invalid: Value is required
✘ Sorry, your reply was invalid: Value is required
✘ Sorry, your reply was invalid: Value is required
✘ Sorry, your reply was invalid: Value is required
✘ Sorry, your reply was invalid: Value is required
✘ Sorry, your reply was invalid: Value is required
✘ Sorry, your reply was invalid: Value is required
✘ Sorry, your reply was invalid: Value is required
? Enter something: something
response string: something

I am not sure if this is desired behavior or not.

Since the renderer does know now about printing the error message it is unable to include those lines in the lineCount used when rewriting the prompt. If we wanted to fix this I think we need to somehow make the prompt renderer render the error message upon validation, but not sure what changes would be required to make this happen.

Ctrl-C doesn't exit

I have yet to find any of my implementations that allow Ctrl-C to exit the application.

When it is going through and collecting from a Choice, all that Ctrl-C does is re-display the choices.

When I hit a required AskOne, it just skips that particular prompt without taking in a value. For example:

func createSpeakerPrompt(city, year string) (err error) {
	var exitCode = true

	for exitCode {
		if city == "" {
			prompt := &survey.Input{
				Message: "Enter the city name:",
			}
			survey.AskOne(prompt, &city, survey.Required)
		}

		if year == "" {
			prompt := &survey.Input{
				Message: "Enter the year:",
			}
			survey.AskOne(prompt, &year, survey.Required)
		}
		speaker.CreateSpeaker("", city, year)
		prompt := &survey.Confirm{
			Message: "Do you want to add another speaker?",
		}
		survey.AskOne(prompt, &exitCode, nil)
	}
	return
}

When you go through that, it will prompt you for the city...if you hit ctrl-c, it will then prompt for the year.

Add support for map[string]interface{} as a result

Currently you can pass a struct with fields to gather answers, however this is not very dynamic and requires the fields to be known up front.

It would be great to be able to pass map[string]interface{} as the thing to populate answers, however currently it fails due to type casting...
reflect.Set: value of type string is not assignable to type map[string]interface {}

Default value not assigned into answers?

First, thank you for creating this great module!
I'm using this module like following, but the default value not assigned to the answer variable...

import "gopkg.in/AlecAivazis/survey.v1"

var questions = []*survey.Question{
	{
		Name: "project_name",
		Prompt: &survey.Input{"What is the project name?", ""},
		Validate: survey.Required,
	},
	{
		Name: "author",
		Prompt: &survey.Input{"Who are you?", ""},
	},
	{
		Name: "version",
		Prompt: &survey.Input{"What version is this app right now?", "0.0.0"},
	},
}

type Answers struct {
	ProjectName string `survey:"project_name"`
	Author string `survey:"author"`
	Version string `survey:"version"`
}

answers := Answers{}

err := survey.Ask(questions, &answers)
if err != nil {
	fmt.Println(err.Error())
}
fmt.Println("Answers", answers)

The answer always be like this

? What is the project name? foo
? Who are you? 
? What version is this app right now? (0.0.0)
Answers {foo  }

Did I make a mistake?

Survey forces me to use []survey.Question for every occasion

Is it possible to use Validate field from []survey.Question within any other function, except Ask? So it goes like every time we need to use Validate or Transform, we have to create a new question array and use it only with Ask, even if it isn't supposed to ask more, than one question. To make things less complicated, I suggest to leave only Ask function cause it carries all the stuff other functions do.

Modify API to allow for non-string result from prompts?

@AlecAivazis, creating an issue to track discussions started in [#28] and [#30] regarding potential API changes to encapsulate variable data returned from prompts (example: MultiChoice could return an []string and Confirm could return a bool).

Thinking about your last suggestion, if I understand what you are saying the usage would look roughly like:

    var simpleQs = []*survey.Question{{
        Name: "name",
    }, {
        Name: "color",
    }, {
        Name: "days",
    }, {
        Name: "happy",
    }}

    answers := struct {
        Name  string
        Color string
        Days  []string
        Happy bool
    }{}

    err := survey.Ask(simpleQs, &answers)

Or more with tags:

    answers := struct {
        UserName   string   `survey:"name"`
        FavColor   string   `survey:"color"`
        PreferDays []string `survey:"days"`
        IsHappy    bool     `survey:"happy"`
    }{}

    err := survey.Ask(simpleQs, &answers)

How would we extend AskOne to work on interface values as well? Perhaps something like:

days := []string{}
err := survey.AskOne(prompt, &days)

I think the usage of this is good from a user perspective. However I think the implementation will be reasonably tricky though (ie lots of code) and we will need to do lots of reflection (which will potentially move some compile-time errors to runtime-errors). So I think it is do-able but non-trivial, and I am not sure the implementation complexity cost would justify the relative ease of use in the API.

Support MultiSelect/Select for survey.Required validator

I think the survey.Required validator logically makes sense for Select/MultiSelect, too.

However using it as a validator in MultiSelect currently gives the following error:

panic: runtime error: comparing uncomparable type []string

goroutine 1 [running]:
github.com/AlecAivazis/survey.Required(0x145c0e0, 0xc420216620, 0xc420216620, 0x0)
	/Users/ahmetb/workspace/gopath-iamutil/src/github.com/AlecAivazis/survey/validate.go:12 +0xc7
github.com/AlecAivazis/survey.Ask(0xc4200b1b90, 0x1, 0x1, 0x1447700, 0xc4201fb1e0, 0x80, 0x1500de0)
	/Users/ahmetb/workspace/gopath-iamutil/src/github.com/AlecAivazis/survey/survey.go:61 +0x16e
github.com/AlecAivazis/survey.AskOne(0x1762aa0, 0xc4202c7300, 0x1447700, 0xc4201fb1e0, 0x15450a8, 0x0, 0x0)
	/Users/ahmetb/workspace/gopath-iamutil/src/github.com/AlecAivazis/survey/survey.go:32 +0xbe

It would be cool to use this validator (or a new one, like survey.HasAnswer) that works with slice semantics.

usability issues for Select and MultiSelect with many options

As I run through my projects and replace prompts with survey I found a few minor usability issues with Select and MultiSelect. Specifically if they have many options it can be too much to present all at once. So here is a dumb example:

? Pick a number:
  1
  2
  3
  4
❯ 5
  6
  7
  8
  9
  10

I would like to add a property to limit the view, perhaps ViewSize so we can focus on just a few options. So setting ViewSize: 5 we would see something like:

? Pick a number:
  3
  4
❯ 5
  6
  7

But we would probably need some markers to indicate there is more Up or Down, so maybe something more like:

? Pick a number:
▲ 3
  4
❯ 5
  6
▼ 7

The next issue is that I would like to enable text focusing for long lists. If you have a Select list of all the US States, you currently would have to hit the Down arrow 49 times to get to Wyoming. Ideally we allow users to just type in W and jump the focus to the closest match starting with the letter.

Support []int for writing indexes in addition to []string

The use case I have is type Product struct { name string, code int }.

So I create a var productNames []string from my []product slice, then pass it to survey.AskOne as MultiSelect options:

if err := survey.AskOne(&survey.MultiSelect{
	Message: "Which products do you want: ",
	Options: productNames,
}, &productAnswers, nil); err != nil {
	log.Fatal(errors.Wrap(err, "failed to prompt"))
}

At the end what I need is a list of product.codes.

In the code above, productAnswers has to be []string. To find the relevant product value that has the name displayed in the options list, I have to do either of the following:

  • create a name to product (map[string]product) mapping and after getting answers, look it up from there.
  • for each answer, iterate over products and find the product that has name==answer.

Both are fine as the list is probably small and these are cheap operations, they just cause extra code to be written.

If survey package supported writing indexes to []ints, it would be really easy to look the actual structs up from the products slice. For example, https://github.com/abiosoft/ishell package returns the answers to MultiSelect as slice of indexes chosen, and it works fine too. So if Write() function copying the answers into value supported both []int and []string for MultiSelect, it would be great.

MultiSelect fails to render a long list

Below you can see a picture of a long list passed to MultiSelect. Issues:

  • default view is the end of the list, even though the cursor is by default at item 0.
  • keeps showing only the end of list no matter where the cursor is moved to.
    • never shows the earlier items. I tried bringing cursor all the way to the end and tried to bring it above Item 102. It never showed Item 101 or things before it.

image

MultiSelect should:

  • adapt to the dynamic terminal height
  • slide the options window displayed along with the cursor

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.