Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/stevedonovan/Penlight.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lua/pl/List.lua2
-rw-r--r--lua/pl/dir.lua137
-rw-r--r--lua/pl/init.lua12
-rw-r--r--lua/pl/lexer.lua36
-rw-r--r--lua/pl/luabalanced.lua5
-rw-r--r--lua/pl/path.lua21
-rw-r--r--lua/pl/seq.lua12
-rw-r--r--lua/pl/utils.lua5
8 files changed, 132 insertions, 98 deletions
diff --git a/lua/pl/List.lua b/lua/pl/List.lua
index f34360c..99fedfe 100644
--- a/lua/pl/List.lua
+++ b/lua/pl/List.lua
@@ -339,7 +339,7 @@ local function tostring_q(val)
end
--- how our list should be rendered as a string. Uses join().
--- @see pl.List:join
+-- @see List:join
function List:__tostring()
return '{'..self:join(',',tostring_q)..'}'
end
diff --git a/lua/pl/dir.lua b/lua/pl/dir.lua
index 15a0386..b45bc94 100644
--- a/lua/pl/dir.lua
+++ b/lua/pl/dir.lua
@@ -101,7 +101,8 @@ function dir.getdirectories(dir)
return _listfiles(dir,false)
end
-local function quote_if_necessary (f)
+local function quote_argument (f)
+ f = path.normcase(f)
if f:find '%s' then
return '"'..f..'"'
else
@@ -112,56 +113,83 @@ end
local alien,no_alien,kernel,CopyFile,MoveFile,GetLastError,win32_errors,cmd_tmpfile
+local function execute_command(cmd,parms)
+ if not cmd_tmpfile then cmd_tmpfile = path.tmpname () end
+ local err = path.is_windows and ' > ' or ' 2> '
+ cmd = cmd..' '..parms..err..cmd_tmpfile
+ --print(cmd)
+ local ret = os.execute(cmd) == 0
+ if not ret then
+ return false,(utils.readfile(cmd_tmpfile):gsub('\n(.*)',''))
+ else
+ return true
+ end
+end
+
+local function find_alien_copyfile ()
+ if not alien and not no_alien then
+ res,alien = pcall(require,'alien')
+ no_alien = not res
+ if no_alien then alien = nil end
+ if alien then
+ -- register the Win32 CopyFile and MoveFile functions
+ local copySpec = {'string','string','int',ret='int',abi='stdcall'}
+ kernel = alien.load('kernel32.dll')
+ CopyFile = kernel.CopyFileA
+ CopyFile:types(copySpec)
+ local moveSpec = {'string','string',ret='int',abi='stdcall'}
+ MoveFile = kernel.MoveFileA
+ MoveFile:types(moveSpec)
+ GetLastError = kernel.GetLastError
+ GetLastError:types{ret ='int', abi='stdcall'}
+ win32_errors = {
+ ERROR_FILE_NOT_FOUND = 2,
+ ERROR_PATH_NOT_FOUND = 3,
+ ERROR_ACCESS_DENIED = 5,
+ ERROR_WRITE_PROTECT = 19,
+ ERROR_BAD_UNIT = 20,
+ ERROR_NOT_READY = 21,
+ ERROR_WRITE_FAULT = 29,
+ ERROR_READ_FAULT = 30,
+ ERROR_SHARING_VIOLATION = 32,
+ ERROR_LOCK_VIOLATION = 33,
+ ERROR_HANDLE_DISK_FULL = 39,
+ ERROR_BAD_NETPATH = 53,
+ ERROR_NETWORK_BUSY = 54,
+ ERROR_DEV_NOT_EXIST = 55,
+ ERROR_FILE_EXISTS = 80,
+ ERROR_OPEN_FAILED = 110,
+ ERROR_INVALID_NAME = 123,
+ ERROR_BAD_PATHNAME = 161,
+ ERROR_ALREADY_EXISTS = 183,
+ }
+ end
+ end
+end
+
+local function two_arguments (f1,f2)
+ return quote_argument(f1)..' '..quote_argument(f2)
+end
+
local function file_op (is_copy,src,dest,flag)
- local null
+ if flag == 1 and path.exists(dest) then
+ return false,"cannot overwrite destination"
+ end
if is_windows then
local res
-- if we haven't tried to load Alien before, then do so
- if not alien and not no_alien then
- res,alien = pcall(require,'alien')
- no_alien = not res
- if no_alien then alien = nil end
- if alien then
- -- register the Win32 CopyFile and MoveFile functions
- local copySpec = {'string','string','int',ret='int',abi='stdcall'}
- kernel = alien.load('kernel32.dll')
- CopyFile = kernel.CopyFileA
- CopyFile:types(copySpec)
- local moveSpec = {'string','string',ret='int',abi='stdcall'}
- MoveFile = kernel.MoveFileA
- MoveFile:types(moveSpec)
- GetLastError = kernel.GetLastError
- GetLastError:types{ret ='int', abi='stdcall'}
- win32_errors = {
- ERROR_FILE_NOT_FOUND = 2,
- ERROR_PATH_NOT_FOUND = 3,
- ERROR_ACCESS_DENIED = 5,
- ERROR_WRITE_PROTECT = 19,
- ERROR_BAD_UNIT = 20,
- ERROR_NOT_READY = 21,
- ERROR_WRITE_FAULT = 29,
- ERROR_READ_FAULT = 30,
- ERROR_SHARING_VIOLATION = 32,
- ERROR_LOCK_VIOLATION = 33,
- ERROR_HANDLE_DISK_FULL = 39,
- ERROR_BAD_NETPATH = 53,
- ERROR_NETWORK_BUSY = 54,
- ERROR_DEV_NOT_EXIST = 55,
- ERROR_FILE_EXISTS = 80,
- ERROR_OPEN_FAILED = 110,
- ERROR_INVALID_NAME = 123,
- ERROR_BAD_PATHNAME = 161,
- ERROR_ALREADY_EXISTS = 183,
- }
- end
- end
- if not cmd_tmpfile then cmd_tmpfile = path.tmpname () end
+ find_alien_copyfile()
-- fallback if there's no Alien, just use DOS commands *shudder*
+ -- 'rename' involves a copy and then deleting the source.
if not CopyFile then
src = path.normcase(src)
dest = path.normcase(dest)
cmd = is_copy and 'copy' or 'rename'
- null = ' > '..cmd_tmpfile
+ local res, err = execute_command('copy',two_arguments(src,dest))
+ if not res then return nil,err end
+ if not is_copy then
+ return execute_command('del',quote_argument(src))
+ end
else
if path.isdir(dest) then
dest = path.join(dest,path.basename(src))
@@ -178,23 +206,8 @@ local function file_op (is_copy,src,dest,flag)
end
end
else -- for Unix, just use cp for now
- if not cmd_tmpfile then cmd_tmpfile = path.tmpname () end
- cmd = is_copy and 'cp' or 'mv'
- null = ' 2> '..cmd_tmpfile
- end
- if flag == 1 and path.exists(dest) then
- return false,"cannot overwrite destination"
- end
- src = quote_if_necessary(src)
- dest = quote_if_necessary(dest)
- -- let's make this as quiet a call as we can...
- cmd = cmd..' '..src..' '..dest..null
- --print(cmd)
- local ret = os.execute(cmd) == 0
- if not ret then
- return false,(utils.readfile(cmd_tmpfile):gsub('\n(.*)',''))
- else
- return true
+ return execute_command(is_copy and 'cp' or 'mv',
+ two_arguments(src,dest))
end
end
@@ -377,15 +390,17 @@ end
function dir.dirtree( d )
assert( d and d ~= "", "directory parameter is missing or empty" )
local exists, isdir = path.exists, path.isdir
+ local sep = path.sep
- if sub( d, -1 ) == "/" then
+ local last = sub ( d, -1 )
+ if last == sep or last == '/' then
d = sub( d, 1, -2 )
end
local function yieldtree( dir )
for entry in ldir( dir ) do
if entry ~= "." and entry ~= ".." then
- entry = dir .. "/" .. entry
+ entry = dir .. sep .. entry
if exists(entry) then -- Just in case a symlink is broken.
local is_dir = isdir(entry)
yield( entry, is_dir )
diff --git a/lua/pl/init.lua b/lua/pl/init.lua
index 3cceb28..b7f84a2 100644
--- a/lua/pl/init.lua
+++ b/lua/pl/init.lua
@@ -1,11 +1,17 @@
--- entry point for loading all PL libraries only on demand!
+--------------
+-- entry point for loading all PL libraries only on demand.
+-- Requiring 'pl' means that whenever a module is accesssed (e.g. utils.split)
+-- then that module is dynamically loaded. The submodules are all brought into
+-- the global space.
+-- @class module
+-- @name pl
local modules = {
utils = true,path=true,dir=true,tablex=true,stringio=true,sip=true,
input=true,seq=true,lexer=true,stringx=true,
config=true,pretty=true,data=true,func=true,text=true,
operator=true,lapp=true,array2d=true,
- comprehension=true,luabalanced=true,
+ comprehension=true,
test = true, app = true, file = true, class = true, List = true,
Map = true, Set = true, OrderedMap = true, MultiMap = true,
Date = true,
@@ -30,7 +36,7 @@ setmetatable(_G,{
-- either way, we load the required module and make it globally available.
if found then
-- e..g pretty.dump causes pl.pretty to become available as 'pretty'
- rawset(_G,name,require('pl.'..name))
+ rawset(_G,name,require('pl.'..name))
return _G[name]
elseif _hook then
return _hook(t,name)
diff --git a/lua/pl/lexer.lua b/lua/pl/lexer.lua
index 7a3aead..d4d674b 100644
--- a/lua/pl/lexer.lua
+++ b/lua/pl/lexer.lua
@@ -1,21 +1,21 @@
--- Lexical scanner for creating a sequence of tokens from text. <br>
--- <p><code>lexer.scan(s)</code> returns an iterator over all tokens found in the
--- string <code>s</code>. This iterator returns two values, a token type string
--- (such as 'string' for quoted string, 'iden' for identifier) and the value of the
+-- <p><code>lexer.scan(s)</code> returns an iterator over all tokens found in the
+-- string <code>s</code>. This iterator returns two values, a token type string
+-- (such as 'string' for quoted string, 'iden' for identifier) and the value of the
-- token.
-- <p>
-- Versions specialized for Lua and C are available; these also handle block comments
--- and classify keywords as 'keyword' tokens. For example:
+-- and classify keywords as 'keyword' tokens. For example:
-- <pre class=example>
-- > s = 'for i=1,n do'
-- > for t,v in lexer.lua(s) do print(t,v) end
-- keyword for
--- iden i
--- = =
+-- iden i
+-- = =
-- number 1
--- , ,
+-- , ,
-- iden n
--- keyword do
+-- keyword do
-- </pre>
-- See the Guide for further <a href="../../index.html#lexer">discussion</a> <br>
-- @class module
@@ -90,15 +90,6 @@ local function cdump(tok)
return yield('comment',tok)
end
--- handling line comments - want to trim off the excess whitespace (and linefeed)
--- and make it a separate space token. Needed because these patterns grab
--- upto and including the line end.
-local function cdump_line(tok)
- local s1 = tok:find '%s*$'
- yield("comment",tok:sub(1,s1-1))
- return yield("space",tok:sub(s1))
-end
-
local function wsdump (tok)
return yield("space",tok)
end
@@ -142,7 +133,6 @@ function lexer.scan (s,matches,filter,options)
if filter.space then filter[wsdump] = true end
if filter.comments then
filter[cdump] = true
- filter[cdump_line] = true
end
end
if not matches then
@@ -205,11 +195,11 @@ function lexer.scan (s,matches,filter,options)
end
if idx > sz then
if file then
- repeat -- next non-empty line
+ --repeat -- next non-empty line
line = line + 1
s = file:read()
if not s then return end
- until not s:match '^%s*$'
+ --until not s:match '^%s*$'
s = s .. '\n'
idx ,sz = 1,#s
break
@@ -311,7 +301,7 @@ function lexer.lua(s,filter,options)
{STRING3,sdump},
{STRING1,sdump},
{STRING2,sdump},
- {'^%-%-.-\n',cdump_line},
+ {'^%-%-.-\n',cdump},
{'^%[%[.+%]%]',sdump_l},
{'^%-%-%[%[.+%]%]',cdump},
{'^==',tdump},
@@ -342,7 +332,7 @@ function lexer.cpp(s,filter,options)
["if"] = true, ["static"] = true, ["const"] = true, ["typedef"] = true,
["enum"] = true, ["char"] = true, ["int"] = true, ["bool"] = true,
["long"] = true, ["float"] = true, ["true"] = true, ["delete"] = true,
- ["double"] = true, ["while"] = true, ["new"] = true,
+ ["double"] = true, ["while"] = true, ["new"] = true,
["namespace"] = true, ["try"] = true, ["catch"] = true,
["switch"] = true, ["case"] = true, ["extern"] = true,
["return"] = true,["default"] = true,['unsigned'] = true,['signed'] = true,
@@ -415,7 +405,7 @@ function lexer.get_separated_list(tok,endtoken,delim)
if not token then return nil,'EOS' end -- end of stream is an error!
if is_end(token,value) and level == 1 then
append(parm_values,tl)
- break
+ break
elseif token == '(' then
level = level + 1
tappend(tl,'(')
diff --git a/lua/pl/luabalanced.lua b/lua/pl/luabalanced.lua
index 1bb051a..96edee2 100644
--- a/lua/pl/luabalanced.lua
+++ b/lua/pl/luabalanced.lua
@@ -1,4 +1,4 @@
--- luabalanced.lua
+--- luabalanced.lua
-- Extracted delimited Lua sequences from strings.[1]
-- Inspired by Damian Conway's Text::Balanced[2] in Perl.
--
@@ -6,7 +6,8 @@
-- [2] http://search.cpan.org/dist/Text-Balanced/lib/Text/Balanced.pm
--
-- (c) 2008, David Manura, Licensed under the same terms as Lua (MIT license).
---
+-- @class module
+-- @name pl.luabalanced
local M = {}
diff --git a/lua/pl/path.lua b/lua/pl/path.lua
index 9a0daf1..4269b75 100644
--- a/lua/pl/path.lua
+++ b/lua/pl/path.lua
@@ -31,7 +31,7 @@ else
if res then
attributes = lfs.attributes
currentdir = lfs.currentdir
- link_attrib = lfs.symlinkattributes
+ link_attrib = lfs.symlinkattributes
else
error("pl.path requires LuaFileSystem")
end
@@ -119,6 +119,18 @@ else
end
local sep,dirsep = path.sep,path.dirsep
+--- are we running Windows?
+-- @class field
+-- @name path.is_windows
+
+--- path separator for this platform.
+-- @class field
+-- @name path.sep
+
+--- separator for PATH for this platform
+-- @class field
+-- @name path.dirsep
+
--- given a path, return the directory part and a file part.
-- if there's no directory part, the first value will be empty
-- @param P A file path
@@ -142,8 +154,11 @@ end
function path.abspath(P)
assert_string(1,P)
if not currentdir then return P end
+ local pwd = currentdir()
if not path.isabs(P) then
- return path.join(currentdir(),P)
+ return path.join(pwd,P)
+ elseif path.is_windows and P:sub(2,2) ~= ':' then
+ return pwd:sub(1,2)..P
else
return P
end
@@ -256,7 +271,7 @@ end
-- unlike os.tmpnam(), it always gives you a writeable path (uses %TMP% on Windows)
function path.tmpname ()
local res = tmpnam()
- if is_windows then res = getenv('TMP')..res end
+ if path.is_windows then res = getenv('TMP')..res end
return res
end
diff --git a/lua/pl/seq.lua b/lua/pl/seq.lua
index c182b7a..20731f2 100644
--- a/lua/pl/seq.lua
+++ b/lua/pl/seq.lua
@@ -112,8 +112,8 @@ end
-- @param optional argument to be passed to predicate as second argument.
function seq.count(iter,condn,arg)
local i = 0
- foreach(iter,function(val)
- if condn(v,arg) then i = i + 1 end
+ seq.foreach(iter,function(val)
+ if condn(val,arg) then i = i + 1 end
end)
return i
end
@@ -148,7 +148,7 @@ end
-- @param iter a sequence
-- @return a List
-- @usage copy(list(ls)) is equal to ls
--- @usage copy(list {1,2,3},List) == List{1,2,3}
+-- @usage copy(list {1,2,3}) == List{1,2,3}
function seq.copy(iter)
local res = {}
for v in default_iter(iter) do
@@ -255,6 +255,7 @@ function seq.unique(iter,returns_table)
local t = count_map(iter)
local res = {}
for k in pairs(t) do tappend(res,k) end
+ table.sort(res)
if returns_table then
return res
else
@@ -361,7 +362,7 @@ function seq.reduce (fun,seq,oldval)
end
local val = seq()
if val==nil then return oldval
- else return fun(oldval,reduce(fun,seq,val))
+ else return fun(oldval,seq.reduce(fun,seq,val))
end
end
@@ -461,6 +462,7 @@ end
-- can't directly look these up in seq because of the wrong argument order...
+local map,reduce,mapmethod = seq.map, seq.reduce, seq.mapmethod
local overrides = {
map = function(self,fun,arg)
return map(fun,self,arg)
@@ -487,7 +489,7 @@ SMT = {
setmetatable(seq,{
__call = function(tbl,iter)
if not callable(iter) then
- if type(iter) == 'table' then iter = list(iter)
+ if type(iter) == 'table' then iter = seq.list(iter)
else return iter
end
end
diff --git a/lua/pl/utils.lua b/lua/pl/utils.lua
index 96867fc..9639455 100644
--- a/lua/pl/utils.lua
+++ b/lua/pl/utils.lua
@@ -273,6 +273,11 @@ local function _string_lambda(f)
end
end
+--- an anonymous function as a string. This string is of the form
+-- '|args| expression'.
+-- @param lf function as a string
+-- @return a function
+-- @usage string_lambda '|x|x+1' (2) == 3
utils.string_lambda = utils.memoize(_string_lambda)
local ops