1 -----------------------------------------------------------------------------
2 -- Little program to download DICT word definitions
3 -- LuaSocket sample files
5 -----------------------------------------------------------------------------
7 -----------------------------------------------------------------------------
8 -- Load required modules
9 -----------------------------------------------------------------------------
11 local string = require("string")
12 local table = require("table")
13 local socket
= require("socket")
14 local url
= require("socket.url")
15 local tp
= require("socket.tp")
18 -----------------------------------------------------------------------------
20 -----------------------------------------------------------------------------
25 -----------------------------------------------------------------------------
27 -----------------------------------------------------------------------------
28 local metat
= { __index
= {} }
30 function open(host
, port
)
31 local tp
= socket
.try(tp
.connect(host
or HOST
, port
or PORT
, TIMEOUT
))
32 return base
.setmetatable({tp
= tp
}, metat
)
35 function metat
.__index
:greet()
36 return socket
.try(self
.tp
:check(220))
39 function metat
.__index
:check(ok
)
40 local code
, status
= socket
.try(self
.tp
:check(ok
))
42 base
.tonumber(socket
.skip(2, string.find(status
, "^%d%d%d (%d*)")))
45 function metat
.__index
:getdef()
46 local line
= socket
.try(self
.tp
:receive())
49 table.insert(def
, line
)
50 line
= socket
.try(self
.tp
:receive())
52 return table.concat(def
, "\n")
55 function metat
.__index
:define(database
, word
)
56 database
= database
or "!"
57 socket
.try(self
.tp
:command("DEFINE", database
.. " " .. word
))
58 local code
, count
= self
:check(150)
62 table.insert(defs
, self
:getdef())
68 function metat
.__index
:match(database
, strat
, word
)
69 database
= database
or "!"
71 socket
.try(self
.tp
:command("MATCH", database
.." ".. strat
.." ".. word
))
74 local line
= socket
.try(self
.tp
:receive())
76 database
, word
= socket
.skip(2, string.find(line
, "(%S+) (.*)"))
77 if not mat
[database
] then mat
[database
] = {} end
78 table.insert(mat
[database
], word
)
79 line
= socket
.try(self
.tp
:receive())
85 function metat
.__index
:quit()
86 self
.tp
:command("QUIT")
87 return self
:check(221)
90 function metat
.__index
:close()
91 return self
.tp
:close()
94 -----------------------------------------------------------------------------
95 -- High-level dict API
96 -----------------------------------------------------------------------------
102 local function there(f
)
103 if f
== "" then return nil
107 local function parse(u
)
108 local t
= socket
.try(url
.parse(u
, default
))
109 socket
.try(t
.scheme
== "dict", "invalid scheme '" .. t
.scheme
.. "'")
110 socket
.try(t
.path
, "invalid path in url")
111 local cmd
, arg
= socket
.skip(2, string.find(t
.path
, "^/(.)(.*)$"))
112 socket
.try(cmd
== "d" or cmd
== "m", "<command> should be 'm' or 'd'")
113 socket
.try(arg
and arg
~= "", "need at least <word> in URL")
114 t
.command
, t
.argument
= cmd
, arg
115 arg
= string.gsub(arg
, "^:([^:]+)", function(f
) t
.word
= f
end)
116 socket
.try(t
.word
, "need at least <word> in URL")
117 arg
= string.gsub(arg
, "^:([^:]*)", function(f
) t
.database
= there(f
) end)
119 arg
= string.gsub(arg
, "^:([^:]*)", function(f
) t
.strat
= there(f
) end)
121 string.gsub(arg
, ":([^:]*)$", function(f
) t
.n
= base
.tonumber(f
) end)
125 local function tget(gett
)
126 local con
= open(gett
.host
, gett
.port
)
128 if gett
.command
== "d" then
129 local def
= con
:define(gett
.database
, gett
.word
)
132 if gett
.n
then return def
[gett
.n
]
134 elseif gett
.command
== "m" then
135 local mat
= con
:match(gett
.database
, gett
.strat
, gett
.word
)
139 else return nil, "invalid command" end
142 local function sget(u
)
143 local gett
= parse(u
)
147 get
= socket
.protect(function(gett
)
148 if base
.type(gett
) == "string" then return sget(gett
)
149 else return tget(gett
) end