lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


For what's worth, here is a little script to try to find dependencies between modules.

It uses a rather brute force approach by simply looking for the literal 'require' followed by another literal string.


For example, using Reuben Thomas' stdlib [1] as a guinea pig:

$ cd lua-stdlib/src
$ lua depend.lua --all *.lua
base io_ext
base list
base strbuf
base string_ext
base table_ext
debug_ext debug_init
debug_ext io_ext
debug_ext string_ext
fstable io_ext
fstable lfs
fstable posix
fstable table_ext
getopt base
getopt io_ext
getopt list
getopt object
getopt string_ext
io_ext base
io_ext package_ext
list base
list table_ext
object table_ext
parser object
table_ext list
tree list
xml base
xml string_ext


The output of depend.lua can be feed to tsort to build a sorted list of module dependencies:

$ lua depend.lua *.lua | tsort -q | tail -r
strbuf
string_ext
base
package_ext
io_ext
list
table_ext
debug_init
lfs
posix
object
debug_ext
fstable
getopt
parser
tree
xml

As always, your mileage may vary.


[1] https://github.com/rrthomas/lua-stdlib
[2] http://en.wikipedia.org/wiki/Tsort_(Unix)


--8<--

local assert = assert
local ipairs = ipairs
local select = select
local pairs = pairs
local print = print

local io = require( 'io' )
local package = require( 'package' )
local table = require( 'table' )

local _ENV = {}

local function GFind( aString, aPattern, anIndex )
  local anIndex = anIndex or 1

  return function()
    local aResult = { aString:find( aPattern, anIndex ) }

    if #aResult == 2 then
      anIndex = aResult[ 2 ] + 1

      return table.unpack( aResult )
    end
  end
end

local function Process( aName )
  local aFile = assert( io.open( aName, 'rb' ) )
  local aMap = {}

  for aLine in aFile:lines() do
    for aStart, anEnd in GFind( aLine, '%c?%p?%s?require%c?%p?%s?' ) do
      local aToken = aLine:sub( anEnd ):match( '(%S+)' ) or ''
      local aToken = aToken:match( '%b\'\'' ) or aToken:match( '%b""' ) or ''
      local aToken = aToken:sub( 2, aToken:len() - 1 )

      if aToken and aToken ~= '' then
        aMap[ aToken ] = true
      end
    end
  end

  aFile:close()

  return aMap
end

local function Print( aName, aMap, showAll )
  local aName = aName:match( '([^/\\]+)$' ):match( '([^.]+)' )
  local aList = {}

  for aKey, aValue in pairs( aMap ) do
    aList[ #aList + 1 ] = aKey
  end

  table.sort( aList )

  for anIndex, aValue in ipairs( aList ) do
    if showAll or ( package.searchpath( aName, package.path ) and package.searchpath( aValue, package.path ) ) then
      print( ( '%s %s' ):format( aName, aValue ) )
    end
  end
end

local function Main( ... )
  local anOffset = 1
  local aCount = select( '#', ... )
  local showAll = false

  if aCount == 0 then
    return
  end

  if select( anOffset, ... ):lower() == '--all' then
    showAll = true
    anOffset = anOffset + 1
  end

  for anIndex = anOffset, aCount do
    local aName = select( anIndex, ... )
    local aMap = Process( aName )

    Print( aName, aMap, showAll )
  end
end

-- usage example:
-- lua depend.lua *.lua | tsort -q | tail -r
-- lua depend.lua --all *.lua | tsort -q | tail -r

Main( ... )

-->8--