diff options
author | mitchell <70453897+667e-11@users.noreply.github.com> | 2013-03-25 01:48:47 -0400 |
---|---|---|
committer | mitchell <70453897+667e-11@users.noreply.github.com> | 2013-03-25 01:48:47 -0400 |
commit | 2fb60bd197071eb6c1da78e65e00aaaa374bdce1 (patch) | |
tree | 7e62cb5c41e97d5879e2c54487403e44a682a8fc /core/lfs_ext.lua | |
parent | 8b8737ea7eab958fe5a9459f02471d6b6efa7021 (diff) |
Added lfs.dir_foreach() for allowing Find in Files to have a filter.
Also moved snapopen module into core as io.snapopen().
Diffstat (limited to 'core/lfs_ext.lua')
-rw-r--r-- | core/lfs_ext.lua | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/core/lfs_ext.lua b/core/lfs_ext.lua new file mode 100644 index 00000000..d79800a4 --- /dev/null +++ b/core/lfs_ext.lua @@ -0,0 +1,97 @@ +-- Copyright 2007-2013 Mitchell mitchell.att.foicica.com. See LICENSE. + +--[[ This comment is for LuaDoc. +--- +-- Extends the `lfs` library to find files in directories. +module('lfs')]] + +--- +-- Filter table containing common binary file extensions and version control +-- folders to exclude when iterating over files and directories using +-- `dir_foreach` when its `exclude_FILTER` argument is `false`. +-- @see dir_foreach +-- @class table +-- @name FILTER +lfs.FILTER = { + extensions = { + 'a', 'bmp', 'bz2', 'class', 'dll', 'exe', 'gif', 'gz', 'jar', 'jpeg', 'jpg', + 'o', 'png', 'so', 'tar', 'tgz', 'tif', 'tiff', 'zip' + }, + folders = {'%.bzr$', '%.git$', '%.hg$', '%.svn$', 'CVS$'} +} + +-- Determines whether or not the given file matches the given filter. +-- @param file The filename. +-- @param filter The filter table. +-- @return boolean `true` or `false`. +local function exclude(file, filter) + if not filter then return false end + local ext = filter.extensions + if ext and ext[file:match('[^%.]+$')] then return true end + for i = 1, #filter do + local patt = filter[i] + if patt:sub(1, 1) ~= '!' then + if file:find(patt) then return true end + else + if not file:find(patt:sub(2)) then return true end + end + end + return false +end + +--- +-- Iterates over all files and sub-directories in the UTF-8-encoded directory +-- *utf8_dir*, calling function *f* on each file found. +-- Files *f* is called on do not match any pattern in string or table *filter*, +-- and, unless *exclude_FILTER* is `true`, `FILTER` as well. A filter table +-- contains Lua patterns that match filenames to exclude, with patterns matching +-- folders to exclude listed in a `folders` sub-table. Patterns starting with +-- '!' exclude files and folders that do not match the pattern that follows. Use +-- a table of raw file extensions assigned to an `extensions` key for fast +-- filtering by extension. All strings must be encoded in `_G._CHARSET`, not +-- UTF-8. +-- @param utf8_dir A UTF-8-encoded directory path to iterate over. +-- @param f Function to call with each full file path found. File paths are +-- **not** encoded in UTF-8, but in `_G._CHARSET`. If *f* returns `false` +-- explicitly, iteration ceases. +-- @param filter Optional filter for files and folders to exclude. +-- @param exclude_FILTER Optional flag indicating whether or not to exclude the +-- default filter `FILTER` in the search. If `false`, adds `FILTER` to +-- *filter*. +-- The default value is `false` to include the default filter. +-- @param recursing Utility flag indicating whether or not this function has +-- been recursively called. This flag is used and set internally, and should +-- not be set otherwise. +-- @see FILTER +-- @name dir_foreach +function lfs.dir_foreach(utf8_dir, f, filter, exclude_FILTER, recursing) + if not recursing then + -- Convert filter to a table from nil or string arguments. + if not filter then filter = {} end + if type(filter) == 'string' then filter = {filter} end + -- Add FILTER to filter unless specified otherwise. + if not exclude_FILTER then + for k, v in pairs(lfs.FILTER) do + if not filter[k] then filter[k] = {} end + local filter_k = filter[k] + for i = 1, #v do filter_k[#filter_k + 1] = v[i] end + end + end + -- Create file extension filter hash table for quick lookups. + local ext = filter.extensions + if ext then for i = 1, #ext do ext[ext[i]] = true end end + end + local dir = utf8_dir:iconv(_CHARSET, 'UTF-8') + local lfs_attributes = lfs.attributes + for file in lfs.dir(dir) do + if not file:find('^%.%.?$') then -- ignore . and .. + file = dir..(not WIN32 and '/' or '\\')..file + local type = lfs_attributes(file, 'mode') + if type == 'directory' and not exclude(file, filter.folders) then + lfs.dir_foreach(file, f, filter, nil, true) + elseif type == 'file' and not exclude(file, filter) then + if f(file) == false then return end + end + end + end +end |