GithubHelp home page GithubHelp logo

lunarmodules / penlight Goto Github PK

View Code? Open in Web Editor NEW
1.8K 65.0 238.0 3.09 MB

A set of pure Lua libraries focusing on input data handling (such as reading configuration files), functional programming (such as map, reduce, placeholder expressions,etc), and OS path management. Much of the functionality is inspired by the Python standard libraries.

Home Page: https://lunarmodules.github.io/Penlight/

License: MIT License

Lua 100.00%
lua luajit penlight lua-library luarocks lua-modules

penlight's People

Contributors

alerque avatar arichard4 avatar bartvm avatar broma0 avatar catwell avatar coolisthename007 avatar cwalther avatar dalange avatar davidxifeng avatar deining avatar elpiloto avatar forkfork avatar geoffleyland avatar greatwolf avatar hishamhm avatar jvprat avatar kalekje avatar kevincox avatar kulla avatar mpeterv avatar nathanrpage97 avatar norman avatar pkazmier avatar riskozoslovenska avatar rjpcomputing avatar ryanjmulder avatar stevedonovan avatar tieske avatar tst2005 avatar user-none avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

penlight's Issues

Lapp and bug

With this code

lapp = require 'pl.lapp'
args = lapp [[
Does some calculations
   -v,--video              (string)             Specify input video
   -w,--width              (default 256)        Width of the video
   -h,--height             (default 144)        Height of the video
   -t,--time               (default 10)         Seconds of video to process
   -k,--seek               (default 0)          Seek number of seconds
   ]] 

weird things happen..

lua test.lua -v abc -t 40 -k 20

works fine, but

lua test.lua -v abc -t 40 -h 20

won't work but the following will

lua test.lua -v abc -t 40 --height 20

I'm confused... 😕 😿

app.parse_args fails on argument requiring argument but none is given

If an argument is passed to parse_args that is supposed to have an argument, but none is given, it fails with:

pl/app.lua:128: attempt to index field '?' (a nil value)

To give a concrete example that reproduces the crash, this can be added to test-args.lua:

-- Check flags that require a value but none are given
flags,args = parse_args({'-n'},{n=true})

I imagine the actual test case for test-args.lua will be a pcall returning true as well as the raised message (a pcall now obviously returns false & the above error message)

lexer.lua Not correctly processes some lines

Sample code:

lexer = require 'pl.lexer'

lines = [[s = "Hello.\\";]]

for tp,val in lexer.lua(lines,{space=true,comments=false},{string=false}) do
   print (val)
end

displays the result:

s
=
"
Hello
.
\
\
"
;

But it is necessary to:

s
=
"Hello.\\"
;

pretty.write fails to write tables with keys other than strings or numbers

Whenever you call pl.pretty.write with a table with keys which are not strings or numbers in clever mode, it crashes because it tries to call method find.

>  return require"pl.pretty".write{[{}] = "crash"}
/home/julien/.luarocks/share/lua/5.1//pl/pretty.lua:78: attempt to call method 'find' (a nil value)
Stack traceback:
  At @/home/julien/.luarocks/share/lua/5.1//pl/pretty.lua:78 (in upvalue is_identifier)
    0075:     local tables = {}
    0076: 
    0077:     local function is_identifier (s)
   *0078:         return (s:find('^[%a_][%w_]*$')) and not keywords[s]
    0079:     end
    0080: 
    0081:     local function put(s)
  At @/home/julien/.luarocks/share/lua/5.1//pl/pretty.lua:149 (in local writeit)
    0146:                     writeit(val,indent,newindent)
    0147:                 else
    0148:                     if not numkey or not used[key] then -- non-array indices
   *0149:                         if numkey or not is_identifier(key) then
    0150:                             key = index(numkey,key)
    0151:                         end
    0152:                         put(indent..key..set)
  At @/home/julien/.luarocks/share/lua/5.1//pl/pretty.lua:163 (in  ?)
    0160:             putln(tostring(t)..',')
    0161:         end
    0162:     end
   *0163:     writeit(tbl,'',space)
    0164:     eat_last_comma()
    0165:     return concat(lines,#space > 0 and '\n' or '')
    0166: end

Unexpected results in tablex.difference with boolean 'false' as value

Given:

result = tablex.difference({v = false}, {v = false})
print(result.v)

--> false

I would expect...

--> nil

Changing 567 - 574 to the following:

for k,v in pairs(s1) do
    if s2[k] == nil then res[k] = v end
end
if symm then
    for k,v in pairs(s2) do
        if s1[k] == nil then res[k] = v end
    end
end

...results in my expected behavior. :) Have I missed something about the intent of difference or did I find a bug?

Use Case:

I want to check for required arguments. If they are required, I set key to true. Not required is false. So, an incoming table with nil for a given key, is nil and anything else is converted to a set with true as the value. Then I go on to check for required values, and then for extra agruements I wasn't expecting.

stringx.expandtabs doesn't align to tabstops

stringx.expandtabs might be more useful if it matched the behaviour of terminals and text editors by aligning tabs to tabstops - that is, for each tab character, insert just the number of spaces needed to reach the next integer multiple of the tab size. Currently it replaces each tab with the specified number of spaces, regardless of where in the string it occurs.

Here's a quick go at implementing this:

function stringx.expandtabs(self,n)
    n = n or 8
    local s, nrep = self, 1
    while nrep > 0 do
        s, nrep = string.gsub(s,
            "()\t",
            function(pos)
                return string.rep(" ", n - ((pos-1) % n))
            end,
            1)
    end
    return s
end

And some tests that it behaves the same way as a terminal/editor:

asserteq(stringx.expandtabs("\t1"),
-- 12345678123456781
  "        1")

asserteq(stringx.expandtabs("\t\t1"),
-- 12345678123456781
  "                1")

asserteq(stringx.expandtabs("1234\t1"),
-- 12345678123456781
  "1234    1")

asserteq(stringx.expandtabs("12345678\t1"),
-- 12345678123456781
  "12345678        1")

asserteq(stringx.expandtabs("1\t1234567\t1"),
-- 12345678123456781
  "1       1234567 1")

I believe this matches the behaviour of str.expandtabs in Python.

OrderedMap inserting new items wit operator [ ]

Hello,

it would be really convenient to implement __newindex metamethod so that when we assign new key, value pair it would act the same as OrderedMap:set(key, value).
E.g.

local map = OrderedMap()
map:set("param1", 123)
map["param2"] = 456

Right now map:iter() would not find the "param2" item, because it was not inserted into map._keys.

What do you think of this update?

Thank you,
Povilas Balciunas

pl.List:clear()

The tremove() call in List:clear() shouldn't include the second parameter "i" since the list gets smaller with each iteration.

Failing / wrong test

Running the tests shows this failure:

lua ./test-data.lua
test-data.lua:216: assertion failed
got:    2013
needed: 2012
these values were not equal
process failed with non-zero result: ./test-data.lua

Further analysis shows, that the assertion itself is wrong: It should test against 2010, not against 2012, because 1266840760 is Mo 22. Feb 12:12:40 UTC 2010. The problem behind is that the Date conversion silently 'fails' on strings. One gets a non-constant date this way.

> d = Date("test")
> print(d)
2013-01-09 21:46:22
> print(d)
2013-01-09 21:46:23
> print(d)
2013-01-09 21:46:24

So, three things to fix:

  1. Date should not silently ignore a string argument
  2. In the test, conversion should call tonumber
  3. The assertion should check against 2010

This patch fixes issues 2 and 3:

diff --git a/tests/test-data.lua b/tests/test-data.lua
index 721590a..3b86367 100644
--- a/tests/test-data.lua
+++ b/tests/test-data.lua
@@ -210,7 +210,8 @@ Time Message
 -- else into one field
 local Date = require 'pl.Date'

-d = data.read(f,{convert={[1]=Date},last_field_collect=true})
+d = data.read(f,{convert={[1]=function (x) return Date(tonumber(x)) end},
+                last_field_collect=true})

 asserteq(#d[1],2)
-asserteq(d[2][1]:year(),2012)
+asserteq(d[2][1]:year(),2010)

luajava typo in rockspec

The rockspec penlight-1.1.0-2.rockspec contains

["pl.platf.luajava"] = "lua/pl/platf/luajava"

This causes luarocks to try to compile it
gcc -O2 -fPIC -I/usr/include/lua5.1 -c lua/pl/platf/luajava -o .o
gcc: error: lua/pl/platf/luajava: No such file or directory
gcc: fatal error: no input files

Changing the rockspec to

["pl.platf.luajava"] = "lua/pl/platf/luajava.lua"

Resolves the problem

Pretty cannot handle binary data

I'm dealing with table values as strings of binary data. When I try to serialize the data using pretty.write the serialization succeeds. However, pretty.read cannot load the data back into a table. It appears that pretty.write is unable to cope with the binary data and ends up truncating its output.

Here are two examples. The first uses pretty with the binary data. You'll notice that the st variable which is the final table with encrypted (binary, string) data run though pretty is missing the ending portion of pretty serialization.

The second example replaces pretty with serpent (https://github.com/pkulchenko/serpent). Serpent is able to serialize and subsequently load the data without issue.

Output of examples:

$ lua pretty-binary-data.lua (https://gist.github.com/4656251)
e == table -> pretty -> encrypt
e == �� ��CY.��?Y�輟�|7���M6%�&���BX���kgGy���s�h��ח�la1-�7�e���D>��4�՞��_��@��%P?I��$�A���kc����dc�ܟ=l�3�C!�ȃ�sһ�ӄu�}F/��?��#g�/�h�gL�

et == { e }

type(et) == table

et == 1

et[1] == �� ��CY.��?Y�輟�|7���M6%�&���BX���kgGy���s�h��ח�la1-�7�e���D>��4�՞��_��@��%P?I��$�A���kc����dc�ܟ=l�3�C!�ȃ�sһ�ӄu�}F/��?��#g�/�h�gL�

st == et -> pretty
st ==
{
[[
�� ��CY.��?Y�輟�|7���M6%�&���BX���kgGy���s�h��ח�la1-�7�e���D>��4�՞��_��@��%P?I��$�A���kc����dc�ܟ=l�3�C!�ȃ�sһ�ӄu�}F/��?��#g�/�h�gL�

pretty.read(st) == should be table with one encrypted string entry
s s[1] or nil e
nil nil not a Lua table

$ lua serpent-binary-data.lua (https://gist.github.com/4656259)
e == table -> pretty -> encrypt
e == �� ��CY.��?Y�輟�|7���M6%�&���BX���kgGy���s�h��ח�la1-�7�e���D>��4�՞��_��@��%P?I��$�A���kc����dc�ܟ=l�3�C!�ȃ�sһ�ӄu�}F/��?��#g�/�h�gL�

et == { e }
type(et) == table

et == 1

et[1] == �� ��CY.��?Y�輟�|7���M6%�&���BX���kgGy���s�h��ח�la1-�7�e���D>��4�՞��_��@��%P?I��$�A���kc����dc�ܟ=l�3�C!�ȃ�sһ�ӄu�}F/��?��#g�/�h�gL�

st == et -> serpent
st ==
do local ={[1]="�� ��CY.��?Y�輟�|7���M6%�&���BX���kgGy���\026s�h��ח�la1-�7�e���D>��4�՞��_��@��%P?I��$�A���kc����dc�ܟ=\026l�3�C!�ȃ�sһ�ӄu�}F/��?��#g�/�h�gL�\000����>|�W�j� �_N��ćw�B\026����E�P�ϼ�H$��ҡ�&ɤ��P�-79PfV�j��\000�FW�.��Q+Xߒ�-j<{-]��d��{���\000��f���9�B��}�nSE����m����3�P׏s��L\n�i�n��gy�(����K%LDRL�\n�ۛ�/�F�+ �"����,�r;�v V��B�ʇ�y��įe\��em��z��k���k�\��H(�C���B�s�B��v��i��q�cn��\026#X&hҚ3����Wf�%2'��C���{V����Q[���䐏L7��3Q�>p����$�B�\�q\ǦS>tR�.�x��o�r��,��!�Y�b\000o�\΋�?L_k���%r4UI�\000��rotT�9���RL;�����d�D%L��Z�pg�P��#����]�U���ⱺS-DzvN�hH6p��VV�8�A�ll*H�V-��c�K��$�^d\n>3ʁ�Q�"};return _;end

f, e = loadstring(st) s=f() == should be table with one encrypted string entry
s s and s[1] or nil e
table: 0x1755d70 �� ��CY.��?Y�輟�|7���M6%�&���BX���kgGy���s�h��ח�la1-�7�e���D>��4�՞��_��@��%P?I��$�A���kc����dc�ܟ=l�3�C!�ȃ�sһ�ӄu�}F/��?��#g�/�h�gL� nil

class.properties to handle _self

Sometimes, I want a class that is handling array data and I want to check input that is entered directly onto the class.

local my_obj = MyClass()
my_obj[1] = "foo"
--the class does some checking or other work, 
--in addition to adding "foo". Such as...
print(my_obj[1])
--> FOO

class.properties works well for this, IF you are working on a member of the object, not directly on indexes of the object, itself.

The following is a patch of the class.properties._class_init function (BTW: _class_init needs documentation! :))

class.properties = class()

function class.properties._class_init(klass, _self)
    local _self = type(_self) == "table" and _self or false

    klass.__index = function(t,key)
        -- normal class lookup!
        local v = klass[key]
        if v then return v end
        -- is it a getter?
        v = rawget(klass,'get_'..key)
        if v then
            return v(t)
        end
        --are we getting/setting self?
        if _self then
            --provide easy access to the proxied table
            --we're not trying for total security.
            --this way set_methods can use self._self for direct access.
            if key == "_self" then 
               return _self 
             --if there is a self getter, then use it.
            elseif klass.get_self then
                return klass.get_self(t, key)
            elseif _self[key] then
                 return _self[key]
            else
                return rawget(_self, '_'..key)
            end
        else
        -- is it a field? 
            return rawget(t, '_'..key)
        end
    end
    klass.__newindex = function (t,key,value)
        -- if there's a setter, use that, otherwise directly set table
        local p = 'set_'..key
        local setter = klass[p]
        if setter then
            setter(t,value)
        elseif _self and klass.set_self then
            klass.set_self(t, key, value)
         else
             rawset(t,key,value)
         end
     end
 end

The additional overhead is not high. Two extra if``s during operation, provided_self` is not used. The code is not much longer, if you remove my over-commenting.

In operation, the get_self and set_self work as expected. No attempt to block access to _self is made, except that it is hidden as an upvalue to the metatable, so that it does not appear in ipairs or pairs operations. Therefore, class construction is made simple by referencing self._self as needed, or simply not providing a set_self method.

require'pl.import_into'(_ENV)
A = class.A(class.properties, {})
function A:set_self(k, v)
    if type(v) ~= "string" then error("I like strings",3) end
    self._self[k] = v
end
function A:get_self(k)
    return self._self[k]:upper()
end

a = A()
a[1] = "hello"
print(a[1])
print(a._self[1])
a[2] = 12

--> HELLO
--> hello
--> lua:./class_self.lua:16: I like strings

Things to consider:

  • pl.pretty.write doesn't pick up nested classes written this way, mostly because it clobbers the __tostring metamethod (which I think it should not do).
  • One might consider providing simple __len, __tostring, __ipairs, __pairs metamethods, only to make it automatic, if the class creator doesn't want to explicitly take care of this. Perhaps the documentation could just simply point this out, in the name of not doing too much for them.
  • Not sure how this would effect class inheritance, where this was a super of something else....

pl.lapp converting arguments ending with numbers to _

When updating from Penlight 0.8.x to 1.0.1 our scripts broke because our argument ended in a number. For an example lapp string see below. Notice the --premake4. It converts automatically the premake4 to premake_ which is unexpected.

lapp string example

local args = lapp [[
    Builds the current project. Run from the root level.

    -t,--target         (string)            One of the following: vs2005, vs2008, gnu, or gmake.
    -b,--build          (default Release)   Project-specific build configuration, usually Debug or Release.
    -i,--installer      (default none)      One of the following: inno or nsis.
    -f,--installerfile  (default none)      The installer source file to pass to the installer, if needed.
    -p,--premake        (default none)      Extra options passed on to premake.
    -m,--teamcity       (default true)      Enable teamcity output.
    -c,--clean                              Clean project sources before building.
    -q,--premake4                           Use premake4
    ]]

Add properly versioned branches

Would it be possible to add versioned branches?

Currently the number of changes accepted is keeping me from using Penlight, many changes (including my own) are bugfixes, but also include some functional changes.

So maybe the master branch for all new developments, and a maintained 'version' branch that only gets bugfixes and fully backwards compatible changes. It would then be safe to use the versioned branch, knowing that nothing will break in the future.

For versioning I would prefer SemVer.

But maybe its too early and the code is not yet mature enough for this (there are still quite some fixes and changes added)

Any thoughts?

seq.reduce uses "seq" as parameter name

seq.reduce uses "seq" as the name of the second parameter, which results in:

lua: /usr/local/share/lua/5.1/pl/seq.lua:366: attempt to index local 'seq' (a function value)

Inspecting the line:

else return fun(oldval,seq.reduce(fun,seq,val))

...shows that it tries to call itself recursively, but in effect indexing the parameter "seq".

Solution: Renaming the parameter makes the function work as expected:

function seq.reduce (fun,s,oldval)
    if not oldval then
        s = default_iter(s)
        oldval = s()
        fun = function_arg(1,fun)
    end
    local val = s()
    if val==nil then return oldval
    else return fun(oldval,seq.reduce(fun,s,val))
    end
end

pl.lapp error when actually passing required parameters

When using pl.lapp I am getting an error with the latest version of Penlight. It correctly shows the help text when no command-line parameters are given.

When you actually specify the required parameter on the command-line you get an error. Please see the example, with output, below.

Example:
local lapp = require( "pl.lapp")

local args = lapp[[
Some description

    <stuff>     (string)       Some stuff.
    -h,--help                  Show help message
]]

for k, v in pairs( args ) do
    print( k, tostring( v ) )
end

Output:
$ lua test/lapp_test.lua something
lua: ./pl/sip.lua:245: argument 3 expected a 'table', got a 'nil'
stack traceback:
[C]: in function 'error'
./pl/utils.lua:326: in function 'assert_arg'
./pl/sip.lua:245: in function <./pl/sip.lua:242>
(tail call): ?
./pl/lapp.lua:250: in function <./pl/lapp.lua:146>
(tail call): ?
test/poot.lua:8: in main chunk
[C]: ?

dir.makepath() errors when path ends in a directory separator

pl.dir.makepath errors when path ends in a directory separator. Please make makepath() accept a full file path (e.g. /my/path/to/a/file.txt), or end in a directory separator.

Lua code:

dir.makepath( "/home/username/Documents/DistanceReport/" )

Error:

lua: /usr/share/lua/5.1/pl/dir.lua:311: attempt to index local 'p' (a nil value)
stack traceback:
/usr/share/lua/5.1/pl/dir.lua:311: in function '_makepath'
/usr/share/lua/5.1/pl/dir.lua:316: in function </usr/share/lua/5.1/pl/dir.lua:309>
(tail call): ?
jobs/graded_distance_per_country.job:131: in function 'InitializeJobs'
src/lysol.lua:234: in function 'main'
src/lysol.lua:286: in main chunk
[C]: ?

support only --long option in lapp?

I'm writing a new command line app with lapp and would like to specify only --long options, but it only allows long options if a short one is also specified.

This seems like a rather arbitrary limitation, is there any good reason not to allow long options without a short counterpart?

It would also be great if the match could be a little more liberal as regards spacing, for example to allow

-s, --short

rather than only

-s,--short

Problem with penlight's pl.pretty.dump

I attempted to use penlight's pl.pretty.dump() for a quick and
dirty document format for a simple utility. Its one-argument form
where the first parameter is the table to dump to stdout works
exactly as documented. Its two-argument form where the second
argument is the name of a file fails with a mysterious error:

E:...>lua
Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
> require 'pl.pretty'
> pl.pretty.dump({}, "test.txt")
utils.assert_string: argument 2 expected a 'string', got a 'table'
stack traceback:
       stdin:1: in main chunk
       [C]: ?

E:...>

Note that the message appears to blame argument 2 of my call to
pl.pretty.dump() for being a table, but it is obviously not a
table. The issue is that the implementation of dump() leverages
pl.util.writefile(), but doesn't pass the table through
pl.pretty.write() to make it into a pretty string first. This is
confounded by the (otherwise rational) decision to make all stack
traces start from the user's call site.

At line 160 of pl/pretty.lua, change:
- return utils.raise(utils.writefile((select(1,...)),t))
+ return utils.raise(utils.writefile((select(1,...)),write(t)))

Lapp `true` default flag

Is it possible to have a flag set to true by default? It looks like flag are always false unless you call them. Or am I missing something here?

Example:

opt = lapp [[           
   --defaultFalse   This flag is false unless it is called
]]

and I am looking for a duale --defaultTrue that turns false once it's called.

Thank you

hardcoded list separator?

this line appears to have a hardcoded list separator; ; while at the same time inserting lsep which seems to be the 'soft-coded' list separator.

Class: can't call inherited methods from initializer

-- animal.lua

class = require 'pl.class'

--------Animal----------
local Animal = class()

function Animal:_init(name)
   self:reset()                  ----> overridden
   self.name = name
end

function Animal:reset()
  self.legs = nil
end

---------Cat------------
local Cat = class(Animal)

function Cat:_init(name,breed)
   self:super(name)  -- must init base!
   self.breed = breed
end

function Cat:reset()
  self.legs = 4
  self:base("reset")         ----> fails when reset is called from _init
end

function Cat:speak(text)
 return 'meow' .. tostring(text)
end

----- Try it -------
local pussycat = Cat("pussycat", "mix-match")

This results in the following error:

C:\Users\Public\Lua\ZeroBrainStudio\bin\lua.exe: C:\Users\Thijs\Desktop\test.lua:27: attempt to call method 'base' (a nil value)
stack traceback:
    C:\Users\Thijs\Desktop\test.lua:27: in function 'reset'
    C:\Users\Thijs\Desktop\test.lua:9: in function '_init'
    c:\users\public\lua\5.1\share\lua\5.1\pl\class.lua:27: in function 'call_ctor'
    c:\users\public\lua\5.1\share\lua\5.1\pl\class.lua:23: in function 'super'
    C:\Users\Thijs\Desktop\test.lua:21: in function '_init'
    c:\users\public\lua\5.1\share\lua\5.1\pl\class.lua:27: in function 'call_ctor'
    c:\users\public\lua\5.1\share\lua\5.1\pl\class.lua:93: in function 'Cat'
    C:\Users\Thijs\Desktop\test.lua:35: in main chunk
    [C]: ?
Program completed in 0.04 seconds (pid: 1744).

The initializer of Animal calls the reset method which is overridden by Cat, so the Cat:reset method is executed and tries to call its ancestor through base but apparently base is not yet available.

It seems the initializer runs while the instance hasn't yet been completely configured (base is still missing). I think this is bad, the initializer should only run after the instance construction has been completed.

seq.reduce and strange order of operations.

I've tried the following:

t = {1, 2, 3, 4, 5}
print(seq.reduce("-", t))

This gives -3 when it should be -13 assuming left-to-right order of operations.

What happens is this: 1-(2-(3-(4-5)))
Expected order: (((1-2)-3)-4)-5

Note that currently it's not using right-to-left order either, but a strange mixture due to the recursion setup.

allow variable arguments in path.join and seq.zip

I'd love to see both of these functions take multiple arguments (as they do in python).

I've replaced the join function in my own code simply enough:

local __join = path.join

function path.join(...)
    local arg, n = {...}, select('#', ...)
    local ret = arg[1]
    for i=2,n do
        ret = __join(ret, arg[i])
    end
    return ret
end

path.lua:30: pl.path requires LuaFileSystem

PATH=/usr/lib/qt4/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/bin/core_perl:/home/zilti/bin:/home/zilti/projects/overgame/lua/lua/src;
export LUA_CPATH=/home/zilti/projects/overgame/lua/libs/?.so;
export LUA_PATH=/home/zilti/projects/overgame/lua/busted/bin/?.lua;
cd lua/busted/bin;
./busted
results in:

stack traceback:
[C]: in function 'error'
/home/zilti/projects/overgame/lua/busted/bin/pl/path.lua:30: in main chunk
[C]: in function 'require'
./busted_bootstrap:5: in main chunk
[C]: in ?

Which it should not.

Any interest in a `tablex.sortkeys` and `tablex.sortvalues`?

Any interest in adding sort functions to tablex that would return an iterator so one could iterate over a table either by sorted keys or sorted values? I'm new to Lua and Penlight so maybe this has already been implemented, but nothing jumped out immediately to me. Thoughts? I'll make a first pass at it if it would be of value.

test 2012 problem

tests/test-data.lua has an assertion with 2012 year. Suggested to fix to

asserteq( d[2][1]:year() >= 2013, true ),

use just plain assert function or introduce new assert functions in penlight besides asserteq.

seq.sort() calls global copy()

'round about line 216 in seq.lua

    212 --- return an iterator to the sorted elements of a sequence.
    213 -- @param iter a sequence
    214 -- @param comp an optional comparison function (comp(x,y) is true if x < y)
    215 function seq.sort(iter,comp)
    216     local t = copy(iter)
    217     tsort(t,comp)
    218     return list(t)
    219 end

the global copy() function is called. I believe you meant to call seq.copy()

Make pl.lapp allow for long options to have dashes (-)

I think it is fairly common to have long options in applications use "-" (dash) to separate words. I tried that in pl.lapp and it is not finding the entire long option. For example:
--no-compression turns into no instead of no-compression, in the arguments table. Can this be made to work?

Many functions don't check their arguments.

There are many functions, (I noticed quite a few in pl.path) that do not assert their arguments. Then they pass these arguments to other functions making it hard to debug.

please add rockspec to repo

benefits;

  1. directly install from local repo while making fixes
  2. rockspec itself can be updated using pull requests

Typo in text.indent

The function text.indent is testing the type of its second argument incorrectly, making it impossible to call without error. Quoting from pl/text.lua surrounding line 55:

function text.indent (s,n,ch)
    assert_arg(1,s,'string')
    assert_arg(2,s,'number')
    return _indent(s,string.rep(ch or ' ',n))
end

The second reference to assert_arg should read assert_arg(2,n,'number'). As it is, it effectively requires that s be both a string and a number, then complains about the type of n.

stringx.strip extra parameter

Hi Steve,
The documentation says :
stringx.strip (self, chrs)

It would indeed be handy to be able to specify a list of characters that needs to be strip from the string like this :

string.strip('../toto/ ', '/. ')
returns : 'toto'

What do you think ?

pl.set __tostring method produces nil value error

I just started playing around with Lua a few days ago. Coming from a Python background, I was incredibly happy to find Penlight. Anyway, while exploring the pl.set module on the interpreter, I noticed that trying to print out a set produced a Set.lua:55: attempt to call method 'join' (a nil value) error. Same with stock Lua 5.1, and same occured when I tried to print a pl.Set in a script. I can't find anything about a join method in Lua, so perhaps something changed with Lua 5.1?

Anyway, I changed the __tostring method in the Set module to use the following code on line 55 instead of the join method, and it appears to work OK and produce the string in the form you wanted:

'['..table.concat(Set.values(self), ',')..']'

Having just started with Lua, I'm not sure if this is an acceptable fix, but if so I'd be happy to send a pull request.

Thanks again for Penlight!

EDIT: Just noticed the Penlight's pl.pretty module, so I could also send a fix using that, if you wish.

tablex.range(1,1) probably should return {1}

Currently tablex.range(start, stop) works fine for cases where stop is greater than start.
But for cases where stop is equal to start the function really should return {start}. And for cases where stop is less than start, the function really should return {}.

Currently it throws an error:

> tablex = require('pl.tablex')
tablex = require('pl.tablex')
> tablex.range(1, 1)
tablex.range(1, 1)
./pl/tablex.lua:322: 'for' step must be a number
stack traceback:
    ./pl/tablex.lua:322: in function 'range'
    stdin:1: in main chunk
    [C]: ?
> tablex.range(1, 0)
tablex.range(1, 0)
./pl/tablex.lua:322: 'for' step must be a number
stack traceback:
    ./pl/tablex.lua:322: in function 'range'
    stdin:1: in main chunk
    [C]: ?

Can't Iterate Over List Directly

In the docs it says you can iterate over a List directaly. This is not working for me. Example below.

#! /usr/bin/env lua

require "pl"

local l = List{"one", "two", "three"}

for s in l do
    print(s)
end

Output:

lua: Desktop/test.lua:7: attempt to call a table value
stack traceback:
    Desktop/test.lua:7: in main chunk
    [C]: ?

Expected output:

one
two
three

utils.load could also check mode

Penlight's Lua 5.1 implementation of utils.load ignores the mode parameter. Perhaps it could check whether the first character is 27 to determine whether the chunk is binary. (cf. http://www.lua.org/bugs.html#5.1.4-1)
Though this might be hard to do when str is a function. Maybe it's not worth the effort.

pl.Date fails to parse is8601 format with zero seconds

This is on the current master branch.
I can reproduce this quite easily:

Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
> Date = require('pl.Date')
> df = Date.Format()
> print(df:parse('2012-04-23T11:24:01'))
2012-04-23 11:24:01
> print(df:parse('2012-04-23T11:24:00'))
nil  out of range: 00 is not between 1 and 60

I assume this has something to do with Lua's arrays being indexed from numeral 1, not zero.

A Way to Load pl Into Table

Not at all a bug, but a patch suggestion (which I've done to my version).

I like to to use the auto-import method of PL for the library that I'm creating. However, I don't want to pollute the global table. To accomplish this, I've added a method to my version of PL , called load_into, which mimics the pl/init.lua file, except:

Upon load, it returns a function that accepts a table and returns a table.

If it receives a table, it injects PL into that table.
It it does not, it uses its own table.

It returns the modified table.

_ENV = require'pl.import_into'(_ENV)
assert(pl == nil and tablex and stringx and List)

In this way, I can pass it _G or _ENV or simply use pl.* as I wish to.

pl.lapp not correctly allowing empty lines in option definition

When I add empty lines to a lapp definition it it fails with this message:

lua: /usr/share/lua/5.1/pl/lapp.lua:238: table index is nil
stack traceback:
    /usr/share/lua/5.1/pl/lapp.lua:238: in function </usr/share/lua/5.1/pl/lapp.lua:146>
    (tail call): ?
    lua2exe.lua:74: in function 'main'
    lua2exe.lua:78: in main chunk
    [C]: ?

Here is a simple example that causes the error: https://gist.github.com/796826

Just run it with no command-line arguments.

Notice: The line that causes the error is
<squishy_file> (string) Squishy file to use to combine Lua source and modules.

Local variable scope bug using templates

Hi,
I'm using your template library. I notice a strange behavior using a variable defined in a tamplate. Here is a sample:

package.path = '/d/penlight/lua/?.lua;' .. package.path
local generator = require 'pl.template'
local var = [[
# local tab = {}
# for i = 1,3 do
    $(i)
#   tab [ #tab ] = i
#   tab [ #tab ] = ' '
# end
$(concat( tab ))
]]
local content = {
    concat = table.concat
}
print(generator.substitute(var, content))

Here is the output of this code:

% lua local.lua
1
2
3

The i local variable defined in the for statement is accessible but not the tab variable defined with local satement.
Is it a bug or am I doing it wrong?
Cheers

A spurious underscore can get appended to the last pl.data's fieldnames

Under the wrong circumstances a spurious underscore can get appended to the last field name returned by pl. data. If you have

Date,Time,Data
2012/1/1,1:30,100

then if things go wrong, fieldnames[3] will be "Data_" rather than "Data".

I'm guessing this only happens when you read a file created on Windows on Unix (i.e., maybe the underscore is replacing the \r of window's \r\n (or vice versa, I can't remember) line ending).

tablex.new fails with missing global "set"

tablex.new fails with missing global set - I suppose this should refer to tablex.set defined just above, thus:

function tablex.new (n,val)
    local res = {}
    tablex.set(res,val,1,n)
    return res
end

BUG? class catch method doesn't work

using the example code

-- animal.lua

class = require 'pl.class'

local Animal = class()

function Animal:_init(name)
   self.name = name
end

function Animal:__tostring()
 return self.name..': '..self:speak()
end

class.Dog(Animal)

function Dog:speak()
 return 'bark'
end

class.Cat(Animal)

function Cat:_init(name,breed)
   self:super(name)  -- must init base!
   self.breed = breed
end

function Cat:speak()
 return 'meow'
end

class.Lion(Cat)

function Lion:speak()
 return 'roar'
end

fido = Dog('Fido')
felix = Cat('Felix','Tabby')
leo = Lion('Leo','African')
leo:catch(function(...) print("no handler for:", ...) end)
leo:circus_act()  -- does not exist, so should trigger catch

And adding the last 2 lines to catch a missing handler, results in:

Program starting as '"C:\Users\Public\Lua\ZeroBrainStudio\bin\lua.exe" -e "io.stdout:setvbuf('no')" "C:\Users\Thijs\Desktop\test.lua"'.
Program 'lua.exe' started in 'C:\Users\Thijs\Dropbox\Lua projects\Penlight' (pid: 7672).
nil table: 00439988
C:\Users\Public\Lua\ZeroBrainStudio\bin\lua.exe: C:\Users\Thijs\Desktop\test.lua:43: loop in gettable
stack traceback:
    C:\Users\Thijs\Desktop\test.lua:43: in main chunk
    [C]: ?
Program completed in 0.04 seconds (pid: 7672).

Is this a bug, or am I doing it wrong?

class() calls constructor of previously created class

I recently updated from a a previous Penlight version to latest git head and have encountered a bug which breaks my code using class() from pl.class. Hopefully this example demonstrates the problem - I don't believe there's any reason for A's constructor to be called when defining class B.

$ cat t.lua
class = require("pl.class").class

A = class()
function A:_init(mandatory)
  assert(mandatory, "tried to initialise instance with no arg")
end
B = class()

$ lua t.lua
lua: t.lua:5: tried to initialise instance with no arg
stack traceback:
  [C]: in function 'assert'
  t.lua:5: in function '_init'
  ./pl/class.lua:18: in function 'call_ctor'
  ./pl/class.lua:84: in function 'class'
  t.lua:7: in main chunk
  [C]: ?

luarock install fails on windows

Using a fresh luarocks install on windows 7 x64
luarocks 2.0.12
Doing
luarocks install penlight
fails with
Error: Build error: Failed copying contents of 'lua' directory.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.