Skip to content

Commit

Permalink
pl.dir: convert dir.walk from coroutines to iterators, take 2 (#350)
Browse files Browse the repository at this point in the history
  • Loading branch information
hishamhm committed Sep 27, 2020
1 parent 1579013 commit e9c35a4
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 52 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

see [CONTRIBUTING.md](CONTRIBUTING.md#release-instructions-for-a-new-version) for release instructions

## unreleased

- fix: dir.walk [#350](https://github.com/lunarmodules/Penlight/pull/350)


## 1.9.1 (2020-09-24)

- released to superseed the 1.9.0 version which was retagged in git after some
Expand Down
87 changes: 35 additions & 52 deletions lua/pl/dir.lua
Original file line number Diff line number Diff line change
Expand Up @@ -271,55 +271,20 @@ local function _dirfiles(dirname,attrib)
end


do
local function _walker(root,bottom_up,attrib)
local dirs,files = _dirfiles(root,attrib)
local i = 0
local before = bottom_up
local after = not bottom_up
local sub_iter

return function()
if before then
before = false
return root,dirs,files
end

while i <= #dirs do
if sub_iter then
local a, b, c = sub_iter()
if a then
return a, b, c
end
end
i = i + 1
local subdir = dirs[i]
if subdir then
sub_iter = _walker(root..path.sep..subdir,bottom_up,attrib)
end
end

if after then
after = false
return root,dirs,files
end
end
end

--- return an iterator which walks through a directory tree starting at root.
-- The iterator returns (root,dirs,files)
-- Note that dirs and files are lists of names (i.e. you must say path.join(root,d)
-- to get the actual full path)
-- If bottom_up is false (or not present), then the entries at the current level are returned
-- before we go deeper. This means that you can modify the returned list of directories before
-- continuing.
-- This is a clone of os.walk from the Python libraries.
-- @string root A starting directory
-- @bool bottom_up False if we start listing entries immediately.
-- @bool follow_links follow symbolic links
-- @return an iterator returning root,dirs,files
-- @raise root must be a directory
function dir.walk(root,bottom_up,follow_links)
--- return an iterator which walks through a directory tree starting at root.
-- The iterator returns (root,dirs,files)
-- Note that dirs and files are lists of names (i.e. you must say path.join(root,d)
-- to get the actual full path)
-- If bottom_up is false (or not present), then the entries at the current level are returned
-- before we go deeper. This means that you can modify the returned list of directories before
-- continuing.
-- This is a clone of os.walk from the Python libraries.
-- @string root A starting directory
-- @bool bottom_up False if we start listing entries immediately.
-- @bool follow_links follow symbolic links
-- @return an iterator returning root,dirs,files
-- @raise root must be a directory
function dir.walk(root,bottom_up,follow_links)
assert_dir(1,root)
local attrib
if path.is_windows or not follow_links then
Expand All @@ -328,10 +293,28 @@ do
attrib = path.link_attrib
end

return _walker(root,bottom_up,attrib)
end
end
local to_scan = { root }
local to_return = {}
local iter = function()
while #to_scan > 0 do
local current_root = table.remove(to_scan)
local dirs,files = _dirfiles(current_root, attrib)
for _, d in ipairs(dirs) do
table.insert(to_scan, current_root..path.sep..d)
end
if not bottom_up then
return current_root, dirs, files
else
table.insert(to_return, { current_root, dirs, files })
end
end
if #to_return > 0 then
return utils.unpack(table.remove(to_return))
end
end

return iter
end

--- remove a whole directory tree.
-- @string fullpath A directory path
Expand Down

0 comments on commit e9c35a4

Please sign in to comment.