summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/luasocket/etc/dict.lua
blob: 8c5b711c139946c9d2bfa5238c1aca0f2b717c4c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
-----------------------------------------------------------------------------
-- Little program to download DICT word definitions
-- LuaSocket sample files
-- Author: Diego Nehab
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
-- Load required modules
-----------------------------------------------------------------------------
local base = _G
local string = require("string")
local table = require("table")
local socket = require("socket")
local url = require("socket.url")
local tp = require("socket.tp")
module("socket.dict")

-----------------------------------------------------------------------------
-- Globals
-----------------------------------------------------------------------------
HOST = "dict.org"
PORT = 2628
TIMEOUT = 10

-----------------------------------------------------------------------------
-- Low-level dict API
-----------------------------------------------------------------------------
local metat = { __index = {} }

function open(host, port)
    local tp = socket.try(tp.connect(host or HOST, port or PORT, TIMEOUT))
    return base.setmetatable({tp = tp}, metat)
end

function metat.__index:greet()
    return socket.try(self.tp:check(220))
end

function metat.__index:check(ok)
    local code, status = socket.try(self.tp:check(ok))
    return code,
        base.tonumber(socket.skip(2, string.find(status, "^%d%d%d (%d*)")))
end

function metat.__index:getdef()
    local line = socket.try(self.tp:receive())
    local def = {}
    while line ~= "." do
        table.insert(def, line)
        line = socket.try(self.tp:receive())
    end
    return table.concat(def, "\n")
end

function metat.__index:define(database, word)
    database = database or "!"
      socket.try(self.tp:command("DEFINE",  database .. " " .. word))
    local code, count = self:check(150)
    local defs = {}
    for i = 1, count do
          self:check(151)
        table.insert(defs, self:getdef())
    end
      self:check(250)
    return defs
end

function metat.__index:match(database, strat, word)
    database = database or "!"
    strat = strat or "."
      socket.try(self.tp:command("MATCH",  database .." ".. strat .." ".. word))
    self:check(152)
    local mat = {}
    local line = socket.try(self.tp:receive())
    while line ~= '.' do
        database, word = socket.skip(2, string.find(line, "(%S+) (.*)"))
        if not mat[database] then mat[database] = {} end
        table.insert(mat[database], word)
        line = socket.try(self.tp:receive())
    end
      self:check(250)
    return mat
end

function metat.__index:quit()
    self.tp:command("QUIT")
    return self:check(221)
end

function metat.__index:close()
    return self.tp:close()
end

-----------------------------------------------------------------------------
-- High-level dict API
-----------------------------------------------------------------------------
local default = {
    scheme = "dict",
    host = "dict.org"
}

local function there(f)
    if f == "" then return nil
    else return f end
end

local function parse(u)
    local t = socket.try(url.parse(u, default))
    socket.try(t.scheme == "dict", "invalid scheme '" .. t.scheme .. "'")
    socket.try(t.path, "invalid path in url")
    local cmd, arg = socket.skip(2, string.find(t.path, "^/(.)(.*)$"))
    socket.try(cmd == "d" or cmd == "m", "<command> should be 'm' or 'd'")
    socket.try(arg and arg ~= "", "need at least <word> in URL")
    t.command, t.argument = cmd, arg
    arg = string.gsub(arg, "^:([^:]+)", function(f) t.word = f end)
    socket.try(t.word, "need at least <word> in URL")
    arg = string.gsub(arg, "^:([^:]*)", function(f) t.database = there(f) end)
    if cmd == "m" then
        arg = string.gsub(arg, "^:([^:]*)", function(f) t.strat = there(f) end)
    end
    string.gsub(arg, ":([^:]*)$", function(f) t.n = base.tonumber(f) end)
    return t
end

local function tget(gett)
    local con = open(gett.host, gett.port)
    con:greet()
    if gett.command == "d" then
        local def = con:define(gett.database, gett.word)
        con:quit()
        con:close()
        if gett.n then return def[gett.n]
        else return def end
    elseif gett.command == "m" then
        local mat = con:match(gett.database, gett.strat, gett.word)
        con:quit()
        con:close()
        return mat
    else return nil, "invalid command" end
end

local function sget(u)
    local gett = parse(u)
    return tget(gett)
end

get = socket.protect(function(gett)
    if base.type(gett) == "string" then return sget(gett)
    else return tget(gett) end
end)