2012-02-04 6 views
28

Se ho una struttura di file come questo:carico Lua-files dal percorso relativo

./main.lua 
./mylib/mylib.lua 
./mylib/mylib-utils.lua 
./mylib/mylib-helpers.lua 
./mylib/mylib-other-stuff.lua 

Da main.lua il file mylib.lua può essere caricato con il percorso completo require('mylib.mylib'). Ma all'interno di mylib.lua vorrei anche caricare altri moduli necessari e non mi sento di specificare sempre il percorso completo (ad esempio mylib.mylib-utils). Se mai dovessi decidere di spostare la cartella avrò molta ricerca e sostituzione. C'è un modo per usare solo la parte relativa del percorso?

UPD. Sto usando Lua con Corona SDK, se questo è importante.

risposta

28

C'è un modo di dedurre il "percorso locale" di un file (più concretamente, la stringa che è stato usato per caricare il file).

Se si sta richiedendo un file all'interno di lib.foo.bar, si potrebbe fare qualcosa di simile:

require 'lib.foo.bar' 

allora si può ottenere il percorso del file come il primo elemento (e unico) ... variabile, quando si sono al di fuori di tutte le funzioni. In altre parole:

-- lib/foo/bar.lua 
local pathOfThisFile = ... -- pathOfThisFile is now 'lib.foo.bar' 

Ora, per ottenere il "cartella" è necessario rimuovere il nome del file. Il modo più semplice è utilizzare la corrispondenza:

local folderOfThisFile = (...):match("(.-)[^%.]+$") -- returns 'lib.foo.' 

E ce l'hai. Ora è possibile anteporre la stringa ad altri nomi di file e l'uso che per richiedere:

require(folderOfThisFile .. 'baz')  -- require('lib.foo.baz') 
require(folderOfThisFile .. 'bazinga') -- require('lib.foo.bazinga') 

Se si sposta bar.lua intorno, folderOfThisFile otterrà automaticamente aggiornati.

+0

Grazie, ha funzionato per il caricamento dei file. Ma quando accedo alle proprietà pubbliche del modulo ho ancora bisogno di specificare il percorso completo (ad es. 'Lib.foo.bar.some_value'). – RocketR

+4

Che non ha nulla a che fare con il caricamento dei file; riflette semplicemente come hai scelto di strutturare la tua Lua.È possibile (ad esempio) restituire una tabella su ogni richiesta e archiviarla in una variabile locale: 'local baz = require (folderOfThisFile .. 'baz')' e quindi fare 'baz.some_value' – kikito

+1

Cool, non l'ho fatto sapere che le funzioni esterne di "..." sono la stringa utilizzata per richiedere il file. –

13

Si può fare

package.path = './mylib/?.lua;' .. package.path 

O

local oldreq = require 
local require = function(s) return oldreq('mylib.' .. s) end 

Poi

-- do all the requires 
require('mylib-utils') 
require('mylib-helpers') 
require('mylib-other-stuff') 

-- and optionally restore the old require, if you did it the second way 
require = oldreq 
+0

Strano. Ho provato a cambiare 'package.path 'e ho pensato che stavo facendo qualcosa di sbagliato perché dice' no field package.preload [' mylib-utils '] ',' no file'./Mylib/mylib-utils.lua''. Ma sto usando Lua all'interno del Corona SDK, forse ha alcune peculiarità con il caricamento dei file. – RocketR

0

Nell'ambiente Lua di Conky sono riuscito a includere il mio common.lua (nella stessa directory) come require(".common"). Notare il carattere punto iniziale ..

0

Sto usando il seguente frammento. Dovrebbe funzionare sia per i file caricati con require, sia per i file chiamati tramite la riga di comando. Quindi utilizzare requireRel anziché require per quelli che si desidera caricare con un percorso relativo.

local requireRel 
if arg and arg[0] then 
    package.path = arg[0]:match("(.-)[^\\/]+$") .. "?.lua;" .. package.path 
    requireRel = require 
elseif ... then 
    local d = (...):match("(.-)[^%.]+$") 
    function requireRel(module) return require(d .. module) end 
end