如承诺一样,这是我的开罗版本。我用Lua编写了它,使用lfs遍历目录。我喜欢这些小挑战,因为它们让我探索我想挖掘已久的API...
lfs和LuaCairo都是跨平台的,所以它应该可以在其他系统上运行(在法语WinXP Pro SP3上测试过)。
我制作了一个第一版,当我遍历树时绘制文件名。优点:没有内存开销。不便之处:我必须预先指定图像大小,因此列表很可能被截断。
所以我制作了这个版本,首先遍历目录树,将其存储在Lua表中。然后,知道文件数,创建适合(至少垂直)的画布并绘制名称。
您可以轻松地在PNG渲染和SVG之间切换。后者的问题:Cairo以低级别生成它,绘制字母而不是使用SVG的文本功能。好吧,至少,它保证即使在没有字体的系统上也能准确呈现。但文件更大...如果之后压缩它以获得.svgz文件,这不是真正的问题。
或者直接生成SVG也不应该太难,我过去使用Lua生成SVG。
require"lfs"
require"lcairo"
local CAIRO = cairo
local PI = math.pi
local TWO_PI = 2 * PI
local dirToList = arg[1] or "C:/PrgCmdLine/tcc"
dirToList = string.gsub(dirToList, "([^/])$", "%1/")
print("Listing: " .. dirToList)
local fileNb = 0
outputType = 'png'
function ListDirectory(dirToList)
local dirListing = {}
for file in lfs.dir(dirToList) do
if file ~= ".." and file ~= "." then
local fileAttr = lfs.attributes(dirToList .. file)
if fileAttr.mode == "directory" then
dirListing[file] = ListDirectory(dirToList .. file .. '/')
else
dirListing[file] = ""
end
fileNb = fileNb + 1
end
end
return dirListing
end
local dirListing = ListDirectory(dirToList)
print("Found " .. fileNb .. " files")
local initialOffsetX = 20
local offsetY = 50
local offsetIncrementX = 20
local offsetIncrementY = 12
local iconOffset = 10
local width = 800
local titleHeight = width/50
local height = offsetIncrementY * (fileNb + 1) + titleHeight
local outfile = "CairoDirTree." .. outputType
local ctxSurface
if outputType == 'svg' then
ctxSurface = cairo.SvgSurface(outfile, width, height)
else
ctxSurface = cairo.ImageSurface(CAIRO.FORMAT_RGB24, width, height)
end
local ctx = cairo.Context(ctxSurface)
function DisplayFile(file, bIsDir, offsetX)
if bIsDir then
ctx:save()
ctx:select_font_face("Sans", CAIRO.FONT_SLANT_NORMAL, CAIRO.FONT_WEIGHT_BOLD)
ctx:set_source_rgb(0.5, 0.0, 0.7)
end
ctx:move_to(offsetX, offsetY)
ctx:show_text(file)
if bIsDir then
ctx:new_sub_path()
ctx:arc(offsetX - iconOffset, offsetY - offsetIncrementY/3, offsetIncrementY/3, 0, TWO_PI)
ctx:set_source_rgb(0.7, 0.0, 0.7)
ctx:fill()
ctx:restore()
end
offsetY = offsetY + offsetIncrementY
end
ctx:set_source_rgb(1.0, 1.0, 1.0)
ctx:paint()
ctx:set_source_rgb(0.0, 0.0, 0.3)
ctx:select_font_face("Sans", CAIRO.FONT_SLANT_NORMAL, CAIRO.FONT_WEIGHT_BOLD)
ctx:set_font_size(titleHeight)
ctx:move_to(5, titleHeight)
ctx:show_text("Directory tree of " .. dirToList)
ctx:select_font_face("Sans", CAIRO.FONT_SLANT_NORMAL, CAIRO.FONT_WEIGHT_NORMAL)
ctx:set_font_size(10)
offsetY = titleHeight * 2
function DisplayDirectory(dirToList, offsetX)
for k, v in pairs(dirToList) do
if type(v) == "table" then
DisplayFile(k, true, offsetX)
DisplayDirectory(v, offsetX + offsetIncrementX)
else
DisplayFile(k, false, offsetX)
end
end
end
DisplayDirectory(dirListing, initialOffsetX)
if outputType == 'svg' then
cairo.show_page(ctx)
else
ctxSurface:write_to_png(outfile)
end
ctx:destroy()
ctxSurface:destroy()
print("Found " .. fileNb .. " files")
当然,您可以更改样式。我没有绘制连接线,因为我认为这并非必要。以后我可能会选择性地添加它们。