XHandler is a bridge between [net/context](https://godoc.org/golang.org/x/net/context) and `http.Handler`.
It lets you enforce `net/context` in your handlers without sacrificing compatibility with existing `http.Handlers` nor imposing a specific router.
Thanks to `net/context` deadline management, `xhandler` is able to enforce a per request deadline and will cancel the context when the client closes the connection unexpectedly.
You may create your own `net/context` aware handler pretty much the same way as you would do with http.Handler.
Read more about xhandler on [Dailymotion engineering blog](http://engineering.dailymotion.com/our-way-to-go/).
// Bridge context aware handlers with http.Handler using xhandler.Handle()
http.Handle("/test",c.Handler(xh))
iferr:=http.ListenAndServe(":8080",nil);err!=nil{
log.Fatal(err)
}
}
```
### Using xmux
Xhandler comes with an optional context aware [muxer](https://github.com/rs/xmux) forked from [httprouter](https://github.com/julienschmidt/httprouter):
```go
packagemain
import(
"fmt"
"log"
"net/http"
"time"
"github.com/rs/xhandler"
"github.com/rs/xmux"
"golang.org/x/net/context"
)
funcmain(){
c:=xhandler.Chain{}
// Append a context-aware middleware handler
c.UseC(xhandler.CloseHandler)
// Another context-aware middleware handler
c.UseC(xhandler.TimeoutHandler(2*time.Second))
mux:=xmux.New()
// Use c.Handler to terminate the chain with your final handler
`cli.go` is simple, fast, and fun package for building command line apps in Go. The goal is to enable developers to write fast and distributable command line applications in an expressive way.
cli is a simple, fast, and fun package for building command line apps in Go. The goal is to enable developers to write fast and distributable command line applications in an expressive way.
## Overview
## Overview
Command line apps are usually so tiny that there is absolutely no reason why your code should *not* be self-documenting. Things like generating help text and parsing command flags/options should not hinder productivity when writing a command line app.
Command line apps are usually so tiny that there is absolutely no reason why your code should *not* be self-documenting. Things like generating help text and parsing command flags/options should not hinder productivity when writing a command line app.
**This is where `cli.go` comes into play.**`cli.go` makes command line programming fun, organized, and expressive!
**This is where cli comes into play.** cli makes command line programming fun, organized, and expressive!
## Installation
## Installation
Make sure you have a working Go environment (go 1.1+ is *required*). [See the install instructions](http://golang.org/doc/install.html).
Make sure you have a working Go environment (go 1.1+ is *required*). [See the install instructions](http://golang.org/doc/install.html).
To install `cli.go`, simply run:
To install cli, simply run:
```
```
$ go get github.com/codegangsta/cli
$ go get github.com/codegangsta/cli
```
```
...
@@ -28,7 +30,7 @@ export PATH=$PATH:$GOPATH/bin
...
@@ -28,7 +30,7 @@ export PATH=$PATH:$GOPATH/bin
## Getting Started
## Getting Started
One of the philosophies behind `cli.go` is that an API should be playful and full of discovery. So a `cli.go` app can be as little as one line of code in `main()`.
One of the philosophies behind cli is that an API should be playful and full of discovery. So a cli app can be as little as one line of code in `main()`.
``` go
``` go
packagemain
packagemain
...
@@ -45,11 +47,16 @@ func main() {
...
@@ -45,11 +47,16 @@ func main() {
This app will run and show help text, but is not very useful. Let's give an action to execute and some help documentation:
This app will run and show help text, but is not very useful. Let's give an action to execute and some help documentation:
<!-- {
"output": "boom! I say!"
} -->
``` go
``` go
packagemain
packagemain
import(
import(
"fmt"
"os"
"os"
"github.com/codegangsta/cli"
"github.com/codegangsta/cli"
)
)
...
@@ -57,10 +64,11 @@ func main() {
...
@@ -57,10 +64,11 @@ func main() {
app:=cli.NewApp()
app:=cli.NewApp()
app.Name="boom"
app.Name="boom"
app.Usage="make an explosive entrance"
app.Usage="make an explosive entrance"
app.Action=func(c*cli.Context){
app.Action=func(c*cli.Context)error{
println("boom! I say!")
fmt.Println("boom! I say!")
returnnil
}
}
app.Run(os.Args)
app.Run(os.Args)
}
}
```
```
...
@@ -73,11 +81,16 @@ Being a programmer can be a lonely job. Thankfully by the power of automation th
...
@@ -73,11 +81,16 @@ Being a programmer can be a lonely job. Thankfully by the power of automation th
Start by creating a directory named `greet`, and within it, add a file, `greet.go` with the following code in it:
Start by creating a directory named `greet`, and within it, add a file, `greet.go` with the following code in it:
<!-- {
"output": "Hello friend!"
} -->
``` go
``` go
packagemain
packagemain
import(
import(
"fmt"
"os"
"os"
"github.com/codegangsta/cli"
"github.com/codegangsta/cli"
)
)
...
@@ -85,8 +98,9 @@ func main() {
...
@@ -85,8 +98,9 @@ func main() {
app:=cli.NewApp()
app:=cli.NewApp()
app.Name="greet"
app.Name="greet"
app.Usage="fight the loneliness!"
app.Usage="fight the loneliness!"
app.Action=func(c*cli.Context){
app.Action=func(c*cli.Context)error{
println("Hello friend!")
fmt.Println("Hello friend!")
returnnil
}
}
app.Run(os.Args)
app.Run(os.Args)
...
@@ -106,7 +120,7 @@ $ greet
...
@@ -106,7 +120,7 @@ $ greet
Hello friend!
Hello friend!
```
```
`cli.go` also generates neat help text:
cli also generates neat help text:
```
```
$ greet help
$ greet help
...
@@ -132,8 +146,9 @@ You can lookup arguments by calling the `Args` function on `cli.Context`.
...
@@ -132,8 +146,9 @@ You can lookup arguments by calling the `Args` function on `cli.Context`.
``` go
``` go
...
...
app.Action=func(c*cli.Context){
app.Action=func(c*cli.Context)error{
println("Hello",c.Args()[0])
fmt.Println("Hello",c.Args()[0])
returnnil
}
}
...
...
```
```
...
@@ -151,16 +166,17 @@ app.Flags = []cli.Flag {
...
@@ -151,16 +166,17 @@ app.Flags = []cli.Flag {
Usage:"language for the greeting",
Usage:"language for the greeting",
},
},
}
}
app.Action=func(c*cli.Context){
app.Action=func(c*cli.Context)error{
name:="someone"
name:="someone"
iflen(c.Args())>0{
ifc.NArg()>0{
name=c.Args()[0]
name=c.Args()[0]
}
}
ifc.String("lang")=="spanish"{
ifc.String("lang")=="spanish"{
println("Hola",name)
fmt.Println("Hola",name)
}else{
}else{
println("Hello",name)
fmt.Println("Hello",name)
}
}
returnnil
}
}
...
...
```
```
...
@@ -178,22 +194,45 @@ app.Flags = []cli.Flag {
...
@@ -178,22 +194,45 @@ app.Flags = []cli.Flag {
Destination:&language,
Destination:&language,
},
},
}
}
app.Action=func(c*cli.Context){
app.Action=func(c*cli.Context)error{
name:="someone"
name:="someone"
iflen(c.Args())>0{
ifc.NArg()>0{
name=c.Args()[0]
name=c.Args()[0]
}
}
iflanguage=="spanish"{
iflanguage=="spanish"{
println("Hola",name)
fmt.Println("Hola",name)
}else{
}else{
println("Hello",name)
fmt.Println("Hello",name)
}
}
returnnil
}
}
...
...
```
```
See full list of flags at http://godoc.org/github.com/codegangsta/cli
See full list of flags at http://godoc.org/github.com/codegangsta/cli
#### Placeholder Values
Sometimes it's useful to specify a flag's value within the usage string itself. Such placeholders are
indicated with back quotes.
For example this:
```go
cli.StringFlag{
Name:"config, c",
Usage:"Load configuration from `FILE`",
}
```
Will result in help output like:
```
--config FILE, -c FILE Load configuration from FILE
```
Note that only the first placeholder is used. Subsequent back-quoted words will be left as-is.
#### Alternate Names
#### Alternate Names
You can set alternate (or short) names for flags by providing a comma-delimited list for the `Name`. e.g.
You can set alternate (or short) names for flags by providing a comma-delimited list for the `Name`. e.g.
...
@@ -238,6 +277,49 @@ app.Flags = []cli.Flag {
...
@@ -238,6 +277,49 @@ app.Flags = []cli.Flag {
}
}
```
```
#### Values from alternate input sources (YAML and others)
There is a separate package altsrc that adds support for getting flag values from other input sources like YAML.
In order to get values for a flag from an alternate input source the following code would be added to wrap an existing cli.Flag like below:
``` go
altsrc.NewIntFlag(cli.IntFlag{Name:"test"})
```
Initialization must also occur for these flags. Below is an example initializing getting data from a yaml file below.
Feel free to put up a pull request to fix a bug or maybe add a feature. I will give it a code review and make sure that it does not break backwards compatibility. If I or any other collaborators agree that it is in line with the vision of the project, we will work with you to get the code into a mergeable state and merge it into the master branch.
Feel free to put up a pull request to fix a bug or maybe add a feature. I will give it a code review and make sure that it does not break backwards compatibility. If I or any other collaborators agree that it is in line with the vision of the project, we will work with you to get the code into a mergeable state and merge it into the master branch.