├── .gitignore ├── vendor ├── github.com │ ├── PuerkitoBio │ │ └── goquery │ │ │ ├── .gitattributes │ │ │ ├── go.mod │ │ │ ├── .gitignore │ │ │ ├── .travis.yml │ │ │ ├── go.sum │ │ │ ├── LICENSE │ │ │ ├── iteration.go │ │ │ ├── query.go │ │ │ ├── expand.go │ │ │ ├── array.go │ │ │ ├── type.go │ │ │ ├── doc.go │ │ │ ├── utilities.go │ │ │ ├── filter.go │ │ │ ├── property.go │ │ │ ├── README.md │ │ │ └── manipulation.go │ ├── andybalholm │ │ └── cascadia │ │ │ ├── go.mod │ │ │ ├── .travis.yml │ │ │ ├── README.md │ │ │ ├── specificity.go │ │ │ └── LICENSE │ └── docopt │ │ └── docopt.go │ │ ├── test_golang.docopt │ │ ├── .gitignore │ │ ├── .travis.yml │ │ ├── error.go │ │ ├── LICENSE │ │ ├── doc.go │ │ ├── token.go │ │ ├── README.md │ │ ├── opts.go │ │ ├── pattern.go │ │ ├── testcases.docopt │ │ └── docopt.go ├── golang.org │ └── x │ │ └── net │ │ ├── AUTHORS │ │ ├── CONTRIBUTORS │ │ ├── PATENTS │ │ ├── LICENSE │ │ └── html │ │ ├── atom │ │ └── atom.go │ │ ├── const.go │ │ ├── doc.go │ │ ├── doctype.go │ │ ├── node.go │ │ ├── escape.go │ │ ├── foreign.go │ │ └── render.go └── modules.txt ├── internal └── api │ ├── response.go │ ├── item.go │ ├── answer_test.go │ ├── answer.go │ └── search.go ├── go.mod ├── go.sum ├── cmd └── so │ └── main.go ├── README.md └── Makefile /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | -------------------------------------------------------------------------------- /vendor/github.com/PuerkitoBio/goquery/.gitattributes: -------------------------------------------------------------------------------- 1 | testdata/* linguist-vendored 2 | -------------------------------------------------------------------------------- /vendor/github.com/andybalholm/cascadia/go.mod: -------------------------------------------------------------------------------- 1 | module "github.com/andybalholm/cascadia" 2 | 3 | require "golang.org/x/net" v0.0.0-20180218175443-cbe0f9307d01 4 | -------------------------------------------------------------------------------- /internal/api/response.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | // Response models a response from the Search API 4 | type Response struct { 5 | Items []Item `json:"items"` 6 | } 7 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/cheat/so 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/PuerkitoBio/goquery v1.5.1 7 | github.com/docopt/docopt.go v0.0.0-20180111231733-ee0de3bc6815 8 | ) 9 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/AUTHORS: -------------------------------------------------------------------------------- 1 | # This source code refers to The Go Authors for copyright purposes. 2 | # The master list of authors is in the main Go distribution, 3 | # visible at http://tip.golang.org/AUTHORS. 4 | -------------------------------------------------------------------------------- /vendor/golang.org/x/net/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This source code was written by the Go contributors. 2 | # The master list of contributors is in the main Go distribution, 3 | # visible at http://tip.golang.org/CONTRIBUTORS. 4 | -------------------------------------------------------------------------------- /vendor/github.com/docopt/docopt.go/test_golang.docopt: -------------------------------------------------------------------------------- 1 | r"""usage: prog [NAME_-2]...""" 2 | $ prog 10 20 3 | {"NAME_-2": ["10", "20"]} 4 | 5 | $ prog 10 6 | {"NAME_-2": ["10"]} 7 | 8 | $ prog 9 | {"NAME_-2": []} 10 | -------------------------------------------------------------------------------- /vendor/github.com/PuerkitoBio/goquery/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/PuerkitoBio/goquery 2 | 3 | require ( 4 | github.com/andybalholm/cascadia v1.1.0 5 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2 6 | ) 7 | 8 | go 1.13 9 | -------------------------------------------------------------------------------- /vendor/github.com/andybalholm/cascadia/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.3 5 | - 1.4 6 | 7 | install: 8 | - go get github.com/andybalholm/cascadia 9 | 10 | script: 11 | - go test -v 12 | 13 | notifications: 14 | email: false 15 | -------------------------------------------------------------------------------- /vendor/github.com/PuerkitoBio/goquery/.gitignore: -------------------------------------------------------------------------------- 1 | # editor temporary files 2 | *.sublime-* 3 | .DS_Store 4 | *.swp 5 | #*.*# 6 | tags 7 | 8 | # direnv config 9 | .env* 10 | 11 | # test binaries 12 | *.test 13 | 14 | # coverage and profilte outputs 15 | *.out 16 | 17 | -------------------------------------------------------------------------------- /vendor/github.com/PuerkitoBio/goquery/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.2.x 5 | - 1.3.x 6 | - 1.4.x 7 | - 1.5.x 8 | - 1.6.x 9 | - 1.7.x 10 | - 1.8.x 11 | - 1.9.x 12 | - 1.10.x 13 | - 1.11.x 14 | - 1.12.x 15 | - 1.13.x 16 | - tip 17 | 18 | -------------------------------------------------------------------------------- /vendor/modules.txt: -------------------------------------------------------------------------------- 1 | # github.com/PuerkitoBio/goquery v1.5.1 2 | github.com/PuerkitoBio/goquery 3 | # github.com/andybalholm/cascadia v1.1.0 4 | github.com/andybalholm/cascadia 5 | # github.com/docopt/docopt.go v0.0.0-20180111231733-ee0de3bc6815 6 | github.com/docopt/docopt.go 7 | # golang.org/x/net v0.0.0-20200202094626-16171245cfb2 8 | golang.org/x/net/html 9 | golang.org/x/net/html/atom 10 | -------------------------------------------------------------------------------- /internal/api/item.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | // Item models Search Response items (questions) 4 | type Item struct { 5 | AnswerCount int `json:"answer_count"` 6 | Answers []Answer `json:"answers"` 7 | Body string `json:"body"` 8 | Link string `json:"link"` 9 | QuestionID int `json:"question_id"` 10 | Score int `json:"score"` 11 | Title string `json:"title"` 12 | } 13 | -------------------------------------------------------------------------------- /vendor/github.com/docopt/docopt.go/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | 24 | # coverage droppings 25 | profile.cov 26 | -------------------------------------------------------------------------------- /vendor/github.com/andybalholm/cascadia/README.md: -------------------------------------------------------------------------------- 1 | # cascadia 2 | 3 | [](https://travis-ci.org/andybalholm/cascadia) 4 | 5 | The Cascadia package implements CSS selectors for use with the parse trees produced by the html package. 6 | 7 | To test CSS selectors without writing Go code, check out [cascadia](https://github.com/suntong/cascadia) the command line tool, a thin wrapper around this package. 8 | 9 | [Refer to godoc here](https://godoc.org/github.com/andybalholm/cascadia). 10 | -------------------------------------------------------------------------------- /vendor/github.com/andybalholm/cascadia/specificity.go: -------------------------------------------------------------------------------- 1 | package cascadia 2 | 3 | // Specificity is the CSS specificity as defined in 4 | // https://www.w3.org/TR/selectors/#specificity-rules 5 | // with the convention Specificity = [A,B,C]. 6 | type Specificity [3]int 7 | 8 | // returns `true` if s < other (strictly), false otherwise 9 | func (s Specificity) Less(other Specificity) bool { 10 | for i := range s { 11 | if s[i] < other[i] { 12 | return true 13 | } 14 | if s[i] > other[i] { 15 | return false 16 | } 17 | } 18 | return false 19 | } 20 | 21 | func (s Specificity) Add(other Specificity) Specificity { 22 | for i, sp := range other { 23 | s[i] += sp 24 | } 25 | return s 26 | } 27 | -------------------------------------------------------------------------------- /vendor/github.com/docopt/docopt.go/.travis.yml: -------------------------------------------------------------------------------- 1 | # Travis CI (http://travis-ci.org/) is a continuous integration 2 | # service for open source projects. This file configures it 3 | # to run unit tests for docopt-go. 4 | 5 | language: go 6 | 7 | go: 8 | - 1.4 9 | - 1.5 10 | - 1.6 11 | - 1.7 12 | - 1.8 13 | - 1.9 14 | - tip 15 | 16 | matrix: 17 | fast_finish: true 18 | 19 | before_install: 20 | - go get golang.org/x/tools/cmd/cover 21 | - go get github.com/mattn/goveralls 22 | 23 | install: 24 | - go get -d -v ./... && go build -v ./... 25 | 26 | script: 27 | - go vet -x ./... 28 | - go test -v ./... 29 | - go test -covermode=count -coverprofile=profile.cov . 30 | 31 | after_script: 32 | - $HOME/gopath/bin/goveralls -coverprofile=profile.cov -service=travis-ci 33 | -------------------------------------------------------------------------------- /vendor/github.com/PuerkitoBio/goquery/go.sum: -------------------------------------------------------------------------------- 1 | github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo= 2 | github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= 3 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 4 | golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 5 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI= 6 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 7 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 8 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 9 | -------------------------------------------------------------------------------- /internal/api/answer_test.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | // TestExtract asserts that Extract properly extracts code blocks from an 8 | // Answer's body 9 | func TestExtract(t *testing.T) { 10 | 11 | // initialize an answer 12 | // NB: important to note is that we only want to extract the 13 | //
blocks, not the inline blocks.
14 | body := `
15 | Try this: 16 | 17 |
18 | fmt.Println("hello, world!")
19 |
20 |
21 | It will write "hello, world!" to stdout`
22 | ans := Answer{Body: body}
23 |
24 | // extract the code blocks
25 | got, err := ans.Extract()
26 | if err != nil {
27 | t.Errorf("failed to extract code: %v", err)
28 | }
29 |
30 | // assert that the expected result was returned
31 | want := `fmt.Println("hello, world!")`
32 | if got != want {
33 | t.Errorf("failed to extract code: want: %s, got: %s", want, got)
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/internal/api/answer.go:
--------------------------------------------------------------------------------
1 | package api
2 |
3 | import (
4 | "fmt"
5 | "strings"
6 |
7 | "github.com/PuerkitoBio/goquery"
8 | )
9 |
10 | // Answer models an answer to a Question
11 | type Answer struct {
12 | AnswerID int `json:"answer_id"`
13 | Body string `json:"body"`
14 | IsAccepted bool `json:"is_accepted"`
15 | Link string `json:"link"`
16 | Score int `json:"score"`
17 | Code string `json:"code"`
18 | }
19 |
20 | // Extract extracts code blocks from the Answer body
21 | func (a *Answer) Extract() (string, error) {
22 | // parse the body string into a DOM
23 | doc, err := goquery.NewDocumentFromReader(strings.NewReader(a.Body))
24 | if err != nil {
25 | return "", fmt.Errorf("failed to parse document: %v", err)
26 | }
27 |
28 | // extract and return code blocks
29 | blocks := []string{}
30 | doc.Find("pre code").Each(func(i int, s *goquery.Selection) {
31 | blocks = append(blocks, s.Text())
32 | })
33 |
34 | return strings.TrimSpace(strings.Join(blocks, "\n")), nil
35 | }
36 |
--------------------------------------------------------------------------------
/vendor/github.com/docopt/docopt.go/error.go:
--------------------------------------------------------------------------------
1 | package docopt
2 |
3 | import (
4 | "fmt"
5 | )
6 |
7 | type errorType int
8 |
9 | const (
10 | errorUser errorType = iota
11 | errorLanguage
12 | )
13 |
14 | func (e errorType) String() string {
15 | switch e {
16 | case errorUser:
17 | return "errorUser"
18 | case errorLanguage:
19 | return "errorLanguage"
20 | }
21 | return ""
22 | }
23 |
24 | // UserError records an error with program arguments.
25 | type UserError struct {
26 | msg string
27 | Usage string
28 | }
29 |
30 | func (e UserError) Error() string {
31 | return e.msg
32 | }
33 | func newUserError(msg string, f ...interface{}) error {
34 | return &UserError{fmt.Sprintf(msg, f...), ""}
35 | }
36 |
37 | // LanguageError records an error with the doc string.
38 | type LanguageError struct {
39 | msg string
40 | }
41 |
42 | func (e LanguageError) Error() string {
43 | return e.msg
44 | }
45 | func newLanguageError(msg string, f ...interface{}) error {
46 | return &LanguageError{fmt.Sprintf(msg, f...)}
47 | }
48 |
49 | var newError = fmt.Errorf
50 |
--------------------------------------------------------------------------------
/vendor/github.com/docopt/docopt.go/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 Keith Batten
4 | Copyright (c) 2016 David Irvine
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | this software and associated documentation files (the "Software"), to deal in
8 | the Software without restriction, including without limitation the rights to
9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | the Software, and to permit persons to whom the Software is furnished to do so,
11 | subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/PuerkitoBio/goquery v1.5.1 h1:PSPBGne8NIUWw+/7vFBV+kG2J/5MOjbzc7154OaKCSE=
2 | github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
3 | github.com/andybalholm/cascadia v1.1.0 h1:BuuO6sSfQNFRu1LppgbD25Hr2vLYW25JvxHs5zzsLTo=
4 | github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
5 | github.com/docopt/docopt.go v0.0.0-20180111231733-ee0de3bc6815 h1:HMAfwOa33y82IaQEKQDfUCiwNlxtM1iw7HLM9ru0RNc=
6 | github.com/docopt/docopt.go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:l7JNRynTRuqe45tpIyItHNqZWTxywYjp87MWTOnU5cg=
7 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
8 | golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
9 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
10 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
11 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
12 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
13 |
--------------------------------------------------------------------------------
/vendor/golang.org/x/net/PATENTS:
--------------------------------------------------------------------------------
1 | Additional IP Rights Grant (Patents)
2 |
3 | "This implementation" means the copyrightable works distributed by
4 | Google as part of the Go project.
5 |
6 | Google hereby grants to You a perpetual, worldwide, non-exclusive,
7 | no-charge, royalty-free, irrevocable (except as stated in this section)
8 | patent license to make, have made, use, offer to sell, sell, import,
9 | transfer and otherwise run, modify and propagate the contents of this
10 | implementation of Go, where such license applies only to those patent
11 | claims, both currently owned or controlled by Google and acquired in
12 | the future, licensable by Google that are necessarily infringed by this
13 | implementation of Go. This grant does not include claims that would be
14 | infringed only as a consequence of further modification of this
15 | implementation. If you or your agent or exclusive licensee institute or
16 | order or agree to the institution of patent litigation against any
17 | entity (including a cross-claim or counterclaim in a lawsuit) alleging
18 | that this implementation of Go or any code incorporated within this
19 | implementation of Go constitutes direct or contributory patent
20 | infringement, or inducement of patent infringement, then any patent
21 | rights granted to you under this License for this implementation of Go
22 | shall terminate as of the date such litigation is filed.
23 |
--------------------------------------------------------------------------------
/vendor/github.com/andybalholm/cascadia/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2011 Andy Balholm. All rights reserved.
2 |
3 | Redistribution and use in source and binary forms, with or without
4 | modification, are permitted provided that the following conditions are
5 | met:
6 |
7 | * Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above
10 | copyright notice, this list of conditions and the following disclaimer
11 | in the documentation and/or other materials provided with the
12 | distribution.
13 |
14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/vendor/github.com/PuerkitoBio/goquery/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2012-2016, Martin Angers & Contributors
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5 |
6 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7 |
8 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9 |
10 | * Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
11 |
12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13 |
--------------------------------------------------------------------------------
/vendor/golang.org/x/net/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2009 The Go Authors. All rights reserved.
2 |
3 | Redistribution and use in source and binary forms, with or without
4 | modification, are permitted provided that the following conditions are
5 | met:
6 |
7 | * Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above
10 | copyright notice, this list of conditions and the following disclaimer
11 | in the documentation and/or other materials provided with the
12 | distribution.
13 | * Neither the name of Google Inc. nor the names of its
14 | contributors may be used to endorse or promote products derived from
15 | this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
--------------------------------------------------------------------------------
/vendor/github.com/PuerkitoBio/goquery/iteration.go:
--------------------------------------------------------------------------------
1 | package goquery
2 |
3 | // Each iterates over a Selection object, executing a function for each
4 | // matched element. It returns the current Selection object. The function
5 | // f is called for each element in the selection with the index of the
6 | // element in that selection starting at 0, and a *Selection that contains
7 | // only that element.
8 | func (s *Selection) Each(f func(int, *Selection)) *Selection {
9 | for i, n := range s.Nodes {
10 | f(i, newSingleSelection(n, s.document))
11 | }
12 | return s
13 | }
14 |
15 | // EachWithBreak iterates over a Selection object, executing a function for each
16 | // matched element. It is identical to Each except that it is possible to break
17 | // out of the loop by returning false in the callback function. It returns the
18 | // current Selection object.
19 | func (s *Selection) EachWithBreak(f func(int, *Selection) bool) *Selection {
20 | for i, n := range s.Nodes {
21 | if !f(i, newSingleSelection(n, s.document)) {
22 | return s
23 | }
24 | }
25 | return s
26 | }
27 |
28 | // Map passes each element in the current matched set through a function,
29 | // producing a slice of string holding the returned values. The function
30 | // f is called for each element in the selection with the index of the
31 | // element in that selection starting at 0, and a *Selection that contains
32 | // only that element.
33 | func (s *Selection) Map(f func(int, *Selection) string) (result []string) {
34 | for i, n := range s.Nodes {
35 | result = append(result, f(i, newSingleSelection(n, s.document)))
36 | }
37 |
38 | return result
39 | }
40 |
--------------------------------------------------------------------------------
/vendor/github.com/PuerkitoBio/goquery/query.go:
--------------------------------------------------------------------------------
1 | package goquery
2 |
3 | import "golang.org/x/net/html"
4 |
5 | // Is checks the current matched set of elements against a selector and
6 | // returns true if at least one of these elements matches.
7 | func (s *Selection) Is(selector string) bool {
8 | return s.IsMatcher(compileMatcher(selector))
9 | }
10 |
11 | // IsMatcher checks the current matched set of elements against a matcher and
12 | // returns true if at least one of these elements matches.
13 | func (s *Selection) IsMatcher(m Matcher) bool {
14 | if len(s.Nodes) > 0 {
15 | if len(s.Nodes) == 1 {
16 | return m.Match(s.Nodes[0])
17 | }
18 | return len(m.Filter(s.Nodes)) > 0
19 | }
20 |
21 | return false
22 | }
23 |
24 | // IsFunction checks the current matched set of elements against a predicate and
25 | // returns true if at least one of these elements matches.
26 | func (s *Selection) IsFunction(f func(int, *Selection) bool) bool {
27 | return s.FilterFunction(f).Length() > 0
28 | }
29 |
30 | // IsSelection checks the current matched set of elements against a Selection object
31 | // and returns true if at least one of these elements matches.
32 | func (s *Selection) IsSelection(sel *Selection) bool {
33 | return s.FilterSelection(sel).Length() > 0
34 | }
35 |
36 | // IsNodes checks the current matched set of elements against the specified nodes
37 | // and returns true if at least one of these elements matches.
38 | func (s *Selection) IsNodes(nodes ...*html.Node) bool {
39 | return s.FilterNodes(nodes...).Length() > 0
40 | }
41 |
42 | // Contains returns true if the specified Node is within,
43 | // at any depth, one of the nodes in the Selection object.
44 | // It is NOT inclusive, to behave like jQuery's implementation, and
45 | // unlike Javascript's .contains, so if the contained
46 | // node is itself in the selection, it returns false.
47 | func (s *Selection) Contains(n *html.Node) bool {
48 | return sliceContains(s.Nodes, n)
49 | }
50 |
--------------------------------------------------------------------------------
/vendor/github.com/docopt/docopt.go/doc.go:
--------------------------------------------------------------------------------
1 | /*
2 | Package docopt parses command-line arguments based on a help message.
3 |
4 | Given a conventional command-line help message, docopt processes the arguments.
5 | See https://github.com/docopt/docopt#help-message-format for a description of
6 | the help message format.
7 |
8 | This package exposes three different APIs, depending on the level of control
9 | required. The first, simplest way to parse your docopt usage is to just call:
10 |
11 | docopt.ParseDoc(usage)
12 |
13 | This will use os.Args[1:] as the argv slice, and use the default parser
14 | options. If you want to provide your own version string and args, then use:
15 |
16 | docopt.ParseArgs(usage, argv, "1.2.3")
17 |
18 | If the last parameter (version) is a non-empty string, it will be printed when
19 | --version is given in the argv slice. Finally, we can instantiate our own
20 | docopt.Parser which gives us control over how things like help messages are
21 | printed and whether to exit after displaying usage messages, etc.
22 |
23 | parser := &docopt.Parser{
24 | HelpHandler: docopt.PrintHelpOnly,
25 | OptionsFirst: true,
26 | }
27 | opts, err := parser.ParseArgs(usage, argv, "")
28 |
29 | In particular, setting your own custom HelpHandler function makes unit testing
30 | your own docs with example command line invocations much more enjoyable.
31 |
32 | All three of these return a map of option names to the values parsed from argv,
33 | and an error or nil. You can get the values using the helpers, or just treat it
34 | as a regular map:
35 |
36 | flag, _ := opts.Bool("--flag")
37 | secs, _ := opts.Int("
63 | var filtered []api.Answer
64 | for _, a := range answers {
65 | if a.Code != "" {
66 | filtered = append(filtered, a)
67 | }
68 | }
69 | answers = filtered
70 |
71 | // optionally constrain the response to --number answers
72 | if opts["--number"] != nil {
73 |
74 | // parse --number into an integer (`limit`)
75 | limit, err := strconv.ParseInt(opts["--number"].(string), 10, 64)
76 | if err != nil {
77 | fmt.Fprintf(os.Stderr, "Failed to parse --number: %v\n", err)
78 | os.Exit(1)
79 | }
80 |
81 | // assert that `answers` <= `limit`
82 | if len(answers) > int(limit) {
83 | answers = answers[0:limit]
84 | }
85 | }
86 |
87 | // output JSON and exit
88 | j, err := json.Marshal(answers)
89 | if err != nil {
90 | fmt.Fprintf(os.Stderr, "Failed to marshal answers: %v\n", err)
91 | os.Exit(1)
92 | }
93 | fmt.Println(string(j))
94 | os.Exit(0)
95 | }
96 |
--------------------------------------------------------------------------------
/vendor/golang.org/x/net/html/atom/atom.go:
--------------------------------------------------------------------------------
1 | // Copyright 2012 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | // Package atom provides integer codes (also known as atoms) for a fixed set of
6 | // frequently occurring HTML strings: tag names and attribute keys such as "p"
7 | // and "id".
8 | //
9 | // Sharing an atom's name between all elements with the same tag can result in
10 | // fewer string allocations when tokenizing and parsing HTML. Integer
11 | // comparisons are also generally faster than string comparisons.
12 | //
13 | // The value of an atom's particular code is not guaranteed to stay the same
14 | // between versions of this package. Neither is any ordering guaranteed:
15 | // whether atom.H1 < atom.H2 may also change. The codes are not guaranteed to
16 | // be dense. The only guarantees are that e.g. looking up "div" will yield
17 | // atom.Div, calling atom.Div.String will return "div", and atom.Div != 0.
18 | package atom // import "golang.org/x/net/html/atom"
19 |
20 | // Atom is an integer code for a string. The zero value maps to "".
21 | type Atom uint32
22 |
23 | // String returns the atom's name.
24 | func (a Atom) String() string {
25 | start := uint32(a >> 8)
26 | n := uint32(a & 0xff)
27 | if start+n > uint32(len(atomText)) {
28 | return ""
29 | }
30 | return atomText[start : start+n]
31 | }
32 |
33 | func (a Atom) string() string {
34 | return atomText[a>>8 : a>>8+a&0xff]
35 | }
36 |
37 | // fnv computes the FNV hash with an arbitrary starting value h.
38 | func fnv(h uint32, s []byte) uint32 {
39 | for i := range s {
40 | h ^= uint32(s[i])
41 | h *= 16777619
42 | }
43 | return h
44 | }
45 |
46 | func match(s string, t []byte) bool {
47 | for i, c := range t {
48 | if s[i] != c {
49 | return false
50 | }
51 | }
52 | return true
53 | }
54 |
55 | // Lookup returns the atom whose name is s. It returns zero if there is no
56 | // such atom. The lookup is case sensitive.
57 | func Lookup(s []byte) Atom {
58 | if len(s) == 0 || len(s) > maxAtomLen {
59 | return 0
60 | }
61 | h := fnv(hash0, s)
62 | if a := table[h&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) {
63 | return a
64 | }
65 | if a := table[(h>>16)&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) {
66 | return a
67 | }
68 | return 0
69 | }
70 |
71 | // String returns a string whose contents are equal to s. In that sense, it is
72 | // equivalent to string(s) but may be more efficient.
73 | func String(s []byte) string {
74 | if a := Lookup(s); a != 0 {
75 | return a.String()
76 | }
77 | return string(s)
78 | }
79 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | so
2 | ==
3 | `so` is a companion binary to [vim-so][]. It queries the Stack Overflow API, and makes
4 | code snippets available to `vim-so`.
5 |
6 |
7 | Installing
8 | ----------
9 | Download the newest release from [Releases][] and manually install it on your
10 | system `PATH`.
11 |
12 |
13 | FAQ
14 | ---
15 | ### Why is this executable necessary? ###
16 | `vim-so` must query the Stack Overflow API for code snippets, yet `vim`
17 | provides no native mechanism for making HTTP requests. This executable bridges
18 | that gap.
19 |
20 | ### Why is this executable not bundled with vim-so? ###
21 | This executable is approximately 6Mb in size. In order to support multiple
22 | platforms (currently six in total), `vim-so` would need to contain a compiled
23 | executable for each, and I do not wish to release a ~40Mb `vim` plugin.
24 |
25 | ### Why was this not written in Python? ###
26 | I have had significant difficulty in the past maintaining Python software that
27 | is distributed among a wide user-base. I'm sidestepping that problem by
28 | distributing an executable.
29 |
30 | ### Can I use this to "manually" search Stack Overflow on the command-line? ###
31 | Not in a convenient way. The executable only outputs JSON.
32 |
33 | ### Why not? ###
34 | Initially, I intended for `so` to support that use-case. However, I backed away
35 | from that goal upon realizing two things:
36 |
37 | 1. It is difficult to display a Stack Overflow thread on the command line with
38 | a user-experience that is equivalent to the browser. The browser provides a
39 | superior experience.
40 |
41 | 2. Signficantly: I've found that search engines do a better job of returning
42 | relevant Stack Overflow threads than Stack Overflow's own API. If the API
43 | doesn't return an adequate response, your preferred search engine will
44 | likely do a better job.
45 |
46 | With that being said, if you're interested in doing this anyway, you may wish
47 | to check out the [how2][] project.
48 |
49 |
50 | ### So is this tool useless? ###
51 | I don't think so. It's imperfect, but seems to get the job done about 50% of
52 | the time. And when it works, it feels a bit magical.
53 |
54 | ### What else should I know? ###
55 | You shouldn't waste your time asking Stack Overflow the same question more than
56 | once. After you've gotten an answer from Stack Overflow - either via `vim-so`
57 | or your web-browser - you should cache it locally using [cheat][] and
58 | [vim-cheat][].
59 |
60 |
61 | [Releases]: https://github.com/cheat/so/releases
62 | [cheat]: https://github.com/cheat/cheat
63 | [how2]: https://github.com/santinic/how2
64 | [vim-cheat]: https://github.com/cheat/vim-cheat
65 | [vim-so]: https://github.com/cheat/vim-so/releases
66 |
--------------------------------------------------------------------------------
/vendor/github.com/PuerkitoBio/goquery/expand.go:
--------------------------------------------------------------------------------
1 | package goquery
2 |
3 | import "golang.org/x/net/html"
4 |
5 | // Add adds the selector string's matching nodes to those in the current
6 | // selection and returns a new Selection object.
7 | // The selector string is run in the context of the document of the current
8 | // Selection object.
9 | func (s *Selection) Add(selector string) *Selection {
10 | return s.AddNodes(findWithMatcher([]*html.Node{s.document.rootNode}, compileMatcher(selector))...)
11 | }
12 |
13 | // AddMatcher adds the matcher's matching nodes to those in the current
14 | // selection and returns a new Selection object.
15 | // The matcher is run in the context of the document of the current
16 | // Selection object.
17 | func (s *Selection) AddMatcher(m Matcher) *Selection {
18 | return s.AddNodes(findWithMatcher([]*html.Node{s.document.rootNode}, m)...)
19 | }
20 |
21 | // AddSelection adds the specified Selection object's nodes to those in the
22 | // current selection and returns a new Selection object.
23 | func (s *Selection) AddSelection(sel *Selection) *Selection {
24 | if sel == nil {
25 | return s.AddNodes()
26 | }
27 | return s.AddNodes(sel.Nodes...)
28 | }
29 |
30 | // Union is an alias for AddSelection.
31 | func (s *Selection) Union(sel *Selection) *Selection {
32 | return s.AddSelection(sel)
33 | }
34 |
35 | // AddNodes adds the specified nodes to those in the
36 | // current selection and returns a new Selection object.
37 | func (s *Selection) AddNodes(nodes ...*html.Node) *Selection {
38 | return pushStack(s, appendWithoutDuplicates(s.Nodes, nodes, nil))
39 | }
40 |
41 | // AndSelf adds the previous set of elements on the stack to the current set.
42 | // It returns a new Selection object containing the current Selection combined
43 | // with the previous one.
44 | // Deprecated: This function has been deprecated and is now an alias for AddBack().
45 | func (s *Selection) AndSelf() *Selection {
46 | return s.AddBack()
47 | }
48 |
49 | // AddBack adds the previous set of elements on the stack to the current set.
50 | // It returns a new Selection object containing the current Selection combined
51 | // with the previous one.
52 | func (s *Selection) AddBack() *Selection {
53 | return s.AddSelection(s.prevSel)
54 | }
55 |
56 | // AddBackFiltered reduces the previous set of elements on the stack to those that
57 | // match the selector string, and adds them to the current set.
58 | // It returns a new Selection object containing the current Selection combined
59 | // with the filtered previous one
60 | func (s *Selection) AddBackFiltered(selector string) *Selection {
61 | return s.AddSelection(s.prevSel.Filter(selector))
62 | }
63 |
64 | // AddBackMatcher reduces the previous set of elements on the stack to those that match
65 | // the mateher, and adds them to the curernt set.
66 | // It returns a new Selection object containing the current Selection combined
67 | // with the filtered previous one
68 | func (s *Selection) AddBackMatcher(m Matcher) *Selection {
69 | return s.AddSelection(s.prevSel.FilterMatcher(m))
70 | }
71 |
--------------------------------------------------------------------------------
/vendor/golang.org/x/net/html/const.go:
--------------------------------------------------------------------------------
1 | // Copyright 2011 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | package html
6 |
7 | // Section 12.2.4.2 of the HTML5 specification says "The following elements
8 | // have varying levels of special parsing rules".
9 | // https://html.spec.whatwg.org/multipage/syntax.html#the-stack-of-open-elements
10 | var isSpecialElementMap = map[string]bool{
11 | "address": true,
12 | "applet": true,
13 | "area": true,
14 | "article": true,
15 | "aside": true,
16 | "base": true,
17 | "basefont": true,
18 | "bgsound": true,
19 | "blockquote": true,
20 | "body": true,
21 | "br": true,
22 | "button": true,
23 | "caption": true,
24 | "center": true,
25 | "col": true,
26 | "colgroup": true,
27 | "dd": true,
28 | "details": true,
29 | "dir": true,
30 | "div": true,
31 | "dl": true,
32 | "dt": true,
33 | "embed": true,
34 | "fieldset": true,
35 | "figcaption": true,
36 | "figure": true,
37 | "footer": true,
38 | "form": true,
39 | "frame": true,
40 | "frameset": true,
41 | "h1": true,
42 | "h2": true,
43 | "h3": true,
44 | "h4": true,
45 | "h5": true,
46 | "h6": true,
47 | "head": true,
48 | "header": true,
49 | "hgroup": true,
50 | "hr": true,
51 | "html": true,
52 | "iframe": true,
53 | "img": true,
54 | "input": true,
55 | "keygen": true,
56 | "li": true,
57 | "link": true,
58 | "listing": true,
59 | "main": true,
60 | "marquee": true,
61 | "menu": true,
62 | "meta": true,
63 | "nav": true,
64 | "noembed": true,
65 | "noframes": true,
66 | "noscript": true,
67 | "object": true,
68 | "ol": true,
69 | "p": true,
70 | "param": true,
71 | "plaintext": true,
72 | "pre": true,
73 | "script": true,
74 | "section": true,
75 | "select": true,
76 | "source": true,
77 | "style": true,
78 | "summary": true,
79 | "table": true,
80 | "tbody": true,
81 | "td": true,
82 | "template": true,
83 | "textarea": true,
84 | "tfoot": true,
85 | "th": true,
86 | "thead": true,
87 | "title": true,
88 | "tr": true,
89 | "track": true,
90 | "ul": true,
91 | "wbr": true,
92 | "xmp": true,
93 | }
94 |
95 | func isSpecialElement(element *Node) bool {
96 | switch element.Namespace {
97 | case "", "html":
98 | return isSpecialElementMap[element.Data]
99 | case "math":
100 | switch element.Data {
101 | case "mi", "mo", "mn", "ms", "mtext", "annotation-xml":
102 | return true
103 | }
104 | case "svg":
105 | switch element.Data {
106 | case "foreignObject", "desc", "title":
107 | return true
108 | }
109 | }
110 | return false
111 | }
112 |
--------------------------------------------------------------------------------
/vendor/github.com/docopt/docopt.go/token.go:
--------------------------------------------------------------------------------
1 | package docopt
2 |
3 | import (
4 | "regexp"
5 | "strings"
6 | "unicode"
7 | )
8 |
9 | type tokenList struct {
10 | tokens []string
11 | errorFunc func(string, ...interface{}) error
12 | err errorType
13 | }
14 | type token string
15 |
16 | func newTokenList(source []string, err errorType) *tokenList {
17 | errorFunc := newError
18 | if err == errorUser {
19 | errorFunc = newUserError
20 | } else if err == errorLanguage {
21 | errorFunc = newLanguageError
22 | }
23 | return &tokenList{source, errorFunc, err}
24 | }
25 |
26 | func tokenListFromString(source string) *tokenList {
27 | return newTokenList(strings.Fields(source), errorUser)
28 | }
29 |
30 | func tokenListFromPattern(source string) *tokenList {
31 | p := regexp.MustCompile(`([\[\]\(\)\|]|\.\.\.)`)
32 | source = p.ReplaceAllString(source, ` $1 `)
33 | p = regexp.MustCompile(`\s+|(\S*<.*?>)`)
34 | split := p.Split(source, -1)
35 | match := p.FindAllStringSubmatch(source, -1)
36 | var result []string
37 | l := len(split)
38 | for i := 0; i < l; i++ {
39 | if len(split[i]) > 0 {
40 | result = append(result, split[i])
41 | }
42 | if i < l-1 && len(match[i][1]) > 0 {
43 | result = append(result, match[i][1])
44 | }
45 | }
46 | return newTokenList(result, errorLanguage)
47 | }
48 |
49 | func (t *token) eq(s string) bool {
50 | if t == nil {
51 | return false
52 | }
53 | return string(*t) == s
54 | }
55 | func (t *token) match(matchNil bool, tokenStrings ...string) bool {
56 | if t == nil && matchNil {
57 | return true
58 | } else if t == nil && !matchNil {
59 | return false
60 | }
61 |
62 | for _, tok := range tokenStrings {
63 | if tok == string(*t) {
64 | return true
65 | }
66 | }
67 | return false
68 | }
69 | func (t *token) hasPrefix(prefix string) bool {
70 | if t == nil {
71 | return false
72 | }
73 | return strings.HasPrefix(string(*t), prefix)
74 | }
75 | func (t *token) hasSuffix(suffix string) bool {
76 | if t == nil {
77 | return false
78 | }
79 | return strings.HasSuffix(string(*t), suffix)
80 | }
81 | func (t *token) isUpper() bool {
82 | if t == nil {
83 | return false
84 | }
85 | return isStringUppercase(string(*t))
86 | }
87 | func (t *token) String() string {
88 | if t == nil {
89 | return ""
90 | }
91 | return string(*t)
92 | }
93 |
94 | func (tl *tokenList) current() *token {
95 | if len(tl.tokens) > 0 {
96 | return (*token)(&(tl.tokens[0]))
97 | }
98 | return nil
99 | }
100 |
101 | func (tl *tokenList) length() int {
102 | return len(tl.tokens)
103 | }
104 |
105 | func (tl *tokenList) move() *token {
106 | if len(tl.tokens) > 0 {
107 | t := tl.tokens[0]
108 | tl.tokens = tl.tokens[1:]
109 | return (*token)(&t)
110 | }
111 | return nil
112 | }
113 |
114 | // returns true if all cased characters in the string are uppercase
115 | // and there are there is at least one cased charcter
116 | func isStringUppercase(s string) bool {
117 | if strings.ToUpper(s) != s {
118 | return false
119 | }
120 | for _, c := range []rune(s) {
121 | if unicode.IsUpper(c) {
122 | return true
123 | }
124 | }
125 | return false
126 | }
127 |
--------------------------------------------------------------------------------
/vendor/golang.org/x/net/html/doc.go:
--------------------------------------------------------------------------------
1 | // Copyright 2010 The Go Authors. All rights reserved.
2 | // Use of this source code is governed by a BSD-style
3 | // license that can be found in the LICENSE file.
4 |
5 | /*
6 | Package html implements an HTML5-compliant tokenizer and parser.
7 |
8 | Tokenization is done by creating a Tokenizer for an io.Reader r. It is the
9 | caller's responsibility to ensure that r provides UTF-8 encoded HTML.
10 |
11 | z := html.NewTokenizer(r)
12 |
13 | Given a Tokenizer z, the HTML is tokenized by repeatedly calling z.Next(),
14 | which parses the next token and returns its type, or an error:
15 |
16 | for {
17 | tt := z.Next()
18 | if tt == html.ErrorToken {
19 | // ...
20 | return ...
21 | }
22 | // Process the current token.
23 | }
24 |
25 | There are two APIs for retrieving the current token. The high-level API is to
26 | call Token; the low-level API is to call Text or TagName / TagAttr. Both APIs
27 | allow optionally calling Raw after Next but before Token, Text, TagName, or
28 | TagAttr. In EBNF notation, the valid call sequence per token is:
29 |
30 | Next {Raw} [ Token | Text | TagName {TagAttr} ]
31 |
32 | Token returns an independent data structure that completely describes a token.
33 | Entities (such as "<") are unescaped, tag names and attribute keys are
34 | lower-cased, and attributes are collected into a []Attribute. For example:
35 |
36 | for {
37 | if z.Next() == html.ErrorToken {
38 | // Returning io.EOF indicates success.
39 | return z.Err()
40 | }
41 | emitToken(z.Token())
42 | }
43 |
44 | The low-level API performs fewer allocations and copies, but the contents of
45 | the []byte values returned by Text, TagName and TagAttr may change on the next
46 | call to Next. For example, to extract an HTML page's anchor text:
47 |
48 | depth := 0
49 | for {
50 | tt := z.Next()
51 | switch tt {
52 | case html.ErrorToken:
53 | return z.Err()
54 | case html.TextToken:
55 | if depth > 0 {
56 | // emitBytes should copy the []byte it receives,
57 | // if it doesn't process it immediately.
58 | emitBytes(z.Text())
59 | }
60 | case html.StartTagToken, html.EndTagToken:
61 | tn, _ := z.TagName()
62 | if len(tn) == 1 && tn[0] == 'a' {
63 | if tt == html.StartTagToken {
64 | depth++
65 | } else {
66 | depth--
67 | }
68 | }
69 | }
70 | }
71 |
72 | Parsing is done by calling Parse with an io.Reader, which returns the root of
73 | the parse tree (the document element) as a *Node. It is the caller's
74 | responsibility to ensure that the Reader provides UTF-8 encoded HTML. For
75 | example, to process each anchor node in depth-first order:
76 |
77 | doc, err := html.Parse(r)
78 | if err != nil {
79 | // ...
80 | }
81 | var f func(*html.Node)
82 | f = func(n *html.Node) {
83 | if n.Type == html.ElementNode && n.Data == "a" {
84 | // Do something with n...
85 | }
86 | for c := n.FirstChild; c != nil; c = c.NextSibling {
87 | f(c)
88 | }
89 | }
90 | f(doc)
91 |
92 | The relevant specifications include:
93 | https://html.spec.whatwg.org/multipage/syntax.html and
94 | https://html.spec.whatwg.org/multipage/syntax.html#tokenization
95 | */
96 | package html // import "golang.org/x/net/html"
97 |
98 | // The tokenization algorithm implemented by this package is not a line-by-line
99 | // transliteration of the relatively verbose state-machine in the WHATWG
100 | // specification. A more direct approach is used instead, where the program
101 | // counter implies the state, such as whether it is tokenizing a tag or a text
102 | // node. Specification compliance is verified by checking expected and actual
103 | // outputs over a test suite rather than aiming for algorithmic fidelity.
104 |
105 | // TODO(nigeltao): Does a DOM API belong in this package or a separate one?
106 | // TODO(nigeltao): How does parsing interact with a JavaScript engine?
107 |
--------------------------------------------------------------------------------
/vendor/github.com/docopt/docopt.go/README.md:
--------------------------------------------------------------------------------
1 | docopt-go
2 | =========
3 |
4 | [](https://travis-ci.org/docopt/docopt.go)
5 | [](https://coveralls.io/github/docopt/docopt.go)
6 | [](https://godoc.org/github.com/docopt/docopt.go)
7 |
8 | An implementation of [docopt](http://docopt.org/) in the [Go](http://golang.org/) programming language.
9 |
10 | **docopt** helps you create *beautiful* command-line interfaces easily:
11 |
12 | ```go
13 | package main
14 |
15 | import (
16 | "fmt"
17 | "github.com/docopt/docopt-go"
18 | )
19 |
20 | func main() {
21 | usage := `Naval Fate.
22 |
23 | Usage:
24 | naval_fate ship new