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.
5
// Package dict implements the Dictionary Server Protocol
6
// as defined in RFC 2229.
7
package dict // import "golang.org/x/net/dict"
15
// A Client represents a client connection to a dictionary server.
20
// Dial returns a new client connected to a dictionary server at
21
// addr on the given network.
22
func Dial(network, addr string) (*Client, error) {
23
text, err := textproto.Dial(network, addr)
27
_, _, err = text.ReadCodeLine(220)
32
return &Client{text: text}, nil
35
// Close closes the connection to the dictionary server.
36
func (c *Client) Close() error {
40
// A Dict represents a dictionary available on the server.
42
Name string // short name of dictionary
43
Desc string // long description
46
// Dicts returns a list of the dictionaries available on the server.
47
func (c *Client) Dicts() ([]Dict, error) {
48
id, err := c.text.Cmd("SHOW DB")
53
c.text.StartResponse(id)
54
defer c.text.EndResponse(id)
56
_, _, err = c.text.ReadCodeLine(110)
60
lines, err := c.text.ReadDotLines()
64
_, _, err = c.text.ReadCodeLine(250)
66
dicts := make([]Dict, len(lines))
67
for i := range dicts {
69
a, _ := fields(lines[i])
71
return nil, textproto.ProtocolError("invalid dictionary: " + lines[i])
79
// A Defn represents a definition.
81
Dict Dict // Dict where definition was found
82
Word string // Word being defined
83
Text []byte // Definition text, typically multiple lines
86
// Define requests the definition of the given word.
87
// The argument dict names the dictionary to use,
88
// the Name field of a Dict returned by Dicts.
90
// The special dictionary name "*" means to look in all the
91
// server's dictionaries.
92
// The special dictionary name "!" means to look in all the
93
// server's dictionaries in turn, stopping after finding the word
95
func (c *Client) Define(dict, word string) ([]*Defn, error) {
96
id, err := c.text.Cmd("DEFINE %s %q", dict, word)
101
c.text.StartResponse(id)
102
defer c.text.EndResponse(id)
104
_, line, err := c.text.ReadCodeLine(150)
110
return nil, textproto.ProtocolError("malformed response: " + line)
112
n, err := strconv.Atoi(a[0])
114
return nil, textproto.ProtocolError("invalid definition count: " + a[0])
116
def := make([]*Defn, n)
117
for i := 0; i < n; i++ {
118
_, line, err = c.text.ReadCodeLine(151)
124
// skip it, to keep protocol in sync
130
d := &Defn{Word: a[0], Dict: Dict{a[1], a[2]}}
131
d.Text, err = c.text.ReadDotBytes()
137
_, _, err = c.text.ReadCodeLine(250)
141
// Fields returns the fields in s.
142
// Fields are space separated unquoted words
143
// or quoted with single or double quote.
144
func fields(s string) ([]string, error) {
148
for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
154
if s[i] == '"' || s[i] == '\'' {
158
for j = i + 1; ; j++ {
160
return nil, textproto.ProtocolError("malformed quoted string")
171
v = append(v, unquote(s[i+1:j-1]))
176
for j = i; j < len(s); j++ {
177
if s[j] == ' ' || s[j] == '\t' || s[j] == '\\' || s[j] == '"' || s[j] == '\'' {
181
v = append(v, s[i:j])
186
if c != ' ' && c != '\t' {
187
return nil, textproto.ProtocolError("quotes not on word boundaries")
194
func unquote(s string) string {
195
if strings.Index(s, "\\") < 0 {
200
for r := 0; r < len(b); r++ {
209
return string(b[0:w])