-------------------------------------------------------------------------------- -- Title: WikiFinder.lua -- Description: Like a square peg in a round hole -- Author: Raphaël Szwarc http://alt.textdrive.com/lua/ -- Creation Date: June 20, 2008 -- Legal: Copyright (C) 2007 Raphaël Szwarc -- Under the terms of the MIT License -- http://www.opensource.org/licenses/mit-license.html -------------------------------------------------------------------------------- -- import dependencies local math = require( 'math' ) local os = require( 'os' ) local Wiki = require( 'Wiki' ) local assert = assert local error = error local getmetatable = getmetatable local pcall = pcall local require = require local setmetatable = setmetatable local type = type -------------------------------------------------------------------------------- -- WikiFinder -------------------------------------------------------------------------------- module( 'WikiFinder' ) _VERSION = '1.0' local self = setmetatable( _M, {} ) local meta = getmetatable( self ) local location = Wiki.Location() local finder = nil -------------------------------------------------------------------------------- -- Utilities -------------------------------------------------------------------------------- local function Directory() local File = require( 'File' ) local aDirectory = File( location, 'wiki', 'finder' ) aDirectory.mkdir = true return aDirectory end local function Finder() if finder == nil then local aCall = function() local File = require( 'File' ) local Finder = require( 'Finder' ) local aDirectory = Directory() local aPath = File( aDirectory.path, 'Finder.db' ).path local aFinder = Finder( 'sqlite3://localhost/' .. aPath ) return aFinder end local ok, aFinder = pcall( aCall ) if ok and aFinder then finder = aFinder else finder = false --error( aFinder ) end end if finder then return finder end end local function Try( aFunction, ... ) local ok, aResult = pcall( aFunction, ... ) if ok then return aResult end --error( aResult ) return nil, aResult end local function Delete( aFinder, aName ) if aFinder then aFinder[ aName ] = false end end local function Shuffle( aList ) local count = #aList math.randomseed( os.time() ) for index = 1, count do local anObject = aList[ index ] local anotherIndex = math.random( index, count ) local anotherObject = aList[ anotherIndex ] aList[ index ] = anotherObject aList[ anotherIndex ] = anObject end return aList end local function List( aDirectory ) local aList = {} local anIndex = 1 for aFile in aDirectory() do if aFile.extension == 'id' then aList[ #aList + 1 ] = aFile end end Shuffle( aList ) return function() local aFile = aList[ anIndex ] if aFile and aFile.exists then anIndex = anIndex + 1 return aFile end end end local function Index( aFinder, aName, aText ) local File = require( 'File' ) local aDirectory = Directory() local aFile = File( aDirectory.path, aName .. '.id' ) aFile.mkdir = true end local function ProcessIndex( aFinder ) if aFinder then local aDirectory = Directory() for aFile in List( aDirectory ) do local WikiContent = require( 'WikiContent' ) local aName = aFile.name:gsub( '%.id', '' ) local aContent = WikiContent( aName ) if aContent and aContent.exists then local WikiService = require( 'WikiService' ) aFinder[ aName ] = WikiService.Text( aContent ) end aFile.delete = true end end end local function Iterator( aFinder, aText ) ProcessIndex( aFinder ) if aFinder then return aFinder( aText ) end return function() end end -------------------------------------------------------------------------------- -- Metamethods -------------------------------------------------------------------------------- function meta:__index( aKey ) for anIndex = 1, 10 do local anIterator = Try( Iterator, Finder(), aKey ) if anIterator then return anIterator end end return function() end end function meta:__newindex( aKey, aValue ) if type( aKey ) == 'string' and type( aValue ) == 'boolean' and aValue == true then return Try( Index, Finder(), aKey ) elseif type( aKey ) == 'string' and type( aValue ) == 'boolean' and aValue == false then return Try( Delete, Finder(), aKey ) end error( ( 'Invalid parameters: %q = %q' ):format( tostring( aKey ), tostring( aValue ) ) ) end function meta:__concat( aValue ) return tostring( self ) .. tostring( aValue ) end function meta:__tostring() return ( '%s/%s' ):format( self._NAME, self._VERSION ) end