ตามที่สัญญาไว้นี่คือเวอร์ชันไคโรของฉัน ฉันเขียนสคริปต์ด้วย Lua โดยใช้ lfs เพื่อเดินตามไดเรกทอรี ฉันชอบความท้าทายเล็ก ๆ น้อย ๆ เหล่านี้เนื่องจากอนุญาตให้ฉันสำรวจ API ที่ฉันต้องการขุดมาระยะหนึ่งแล้ว ...
lfs และ LuaCairo ต่างก็ข้ามแพลตฟอร์มดังนั้นจึงควรทำงานบนระบบอื่น ๆ (ทดสอบบน WinXP Pro SP3 ของฝรั่งเศส)
ฉันสร้างชื่อไฟล์รูปวาดเวอร์ชันแรกขณะที่ฉันเดินบนต้นไม้ ข้อดี: ไม่มีหน่วยความจำเหนือศีรษะ ไม่สะดวก: ฉันต้องระบุขนาดของภาพไว้ล่วงหน้าดังนั้นรายชื่อจึงน่าจะถูกตัดออก
ดังนั้นฉันจึงสร้างเวอร์ชันนี้โดยเริ่มจากการเดินแผนผังไดเร็กทอรีโดยจัดเก็บไว้ในตาราง Lua จากนั้นรู้จำนวนไฟล์สร้างผืนผ้าใบให้พอดี (อย่างน้อยในแนวตั้ง) และวาดชื่อ
คุณสามารถสลับระหว่างการแสดงผล PNG และ SVG หนึ่งได้อย่างง่ายดาย ปัญหาหลัง: ไคโรสร้างมันในระดับต่ำโดยวาดตัวอักษรแทนการใช้ความสามารถของข้อความ SVG อย่างน้อยก็รับประกันการเรนเดอร์ที่แม่นยำแม้ในระบบที่ไม่มีฟอนต์ แต่ไฟล์ใหญ่กว่า ... ไม่ใช่ปัญหาจริงๆถ้าคุณบีบอัดหลังจากนั้นให้มีไฟล์. svgz
หรือไม่ควรจะยากเกินไปที่จะสร้าง SVG โดยตรงฉันเคยใช้ Lua เพื่อสร้าง SVG ในอดีต
-- LuaFileSystem <http://www.keplerproject.org/luafilesystem/>
require"lfs"
-- LuaCairo <http://www.dynaset.org/dogusanh/>
require"lcairo"
local CAIRO = cairo
local PI = math.pi
local TWO_PI = 2 * PI
--~ local dirToList = arg[1] or "C:/PrgCmdLine/Graphviz"
--~ local dirToList = arg[1] or "C:/PrgCmdLine/Tecgraf"
local dirToList = arg[1] or "C:/PrgCmdLine/tcc"
-- Ensure path ends with /
dirToList = string.gsub(dirToList, "([^/])$", "%1/")
print("Listing: " .. dirToList)
local fileNb = 0
--~ outputType = 'svg'
outputType = 'png'
-- dirToList must have a trailing slash
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
--dofile[[../Lua/DumpObject.lua]] -- My own dump routine
local dirListing = ListDirectory(dirToList)
--~ print("\n" .. DumpObject(dirListing))
print("Found " .. fileNb .. " files")
--~ os.exit()
-- Constants to change to adjust aspect
local initialOffsetX = 20
local offsetY = 50
local offsetIncrementX = 20
local offsetIncrementY = 12
local iconOffset = 10
local width = 800 -- Still arbitrary
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)
-- Display a file name
-- file is the file name to display
-- offsetX is the indentation
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
-- Display file name
ctx:move_to(offsetX, offsetY)
ctx:show_text(file)
if bIsDir then
ctx:new_sub_path() -- Position independent of latest move_to
-- Draw arc with absolute coordinates
ctx:arc(offsetX - iconOffset, offsetY - offsetIncrementY/3, offsetIncrementY/3, 0, TWO_PI)
-- Violet disk
ctx:set_source_rgb(0.7, 0.0, 0.7)
ctx:fill()
ctx:restore() -- Restore original settings
end
-- Increment line offset
offsetY = offsetY + offsetIncrementY
end
-- Erase background (white)
ctx:set_source_rgb(1.0, 1.0, 1.0)
ctx:paint()
--~ ctx:set_line_width(0.01)
-- Draw in dark blue
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)
-- Display title
ctx:show_text("Directory tree of " .. dirToList)
-- Select font for file names
ctx:select_font_face("Sans", CAIRO.FONT_SLANT_NORMAL, CAIRO.FONT_WEIGHT_NORMAL)
ctx:set_font_size(10)
offsetY = titleHeight * 2
-- Do the job
function DisplayDirectory(dirToList, offsetX)
for k, v in pairs(dirToList) do
--~ print(k, v)
if type(v) == "table" then
-- Sub-directory
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
--cairo.surface_write_to_png(ctxSurface, outfile)
ctxSurface:write_to_png(outfile)
end
ctx:destroy()
ctxSurface:destroy()
print("Found " .. fileNb .. " files")
แน่นอนคุณสามารถเปลี่ยนรูปแบบ ฉันไม่ได้วาดเส้นเชื่อมต่อฉันไม่เห็นว่ามันจำเป็น ฉันอาจเพิ่มทางเลือกในภายหลัง