2012-02-04 12 views
28

Si tengo una estructura de archivos como esto:carga Lua-archivos por ruta relativa

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

De main.lua el archivo mylib.lua se puede cargar con ruta completa require('mylib.mylib'). Pero dentro de mylib.lua también me gustaría cargar otros módulos necesarios y no tengo ganas de especificar siempre la ruta completa (por ejemplo, mylib.mylib-utils). Si alguna vez decidiera mover la carpeta, tendré que buscar y reemplazar mucho. ¿Hay alguna manera de usar solo la parte relativa de la ruta?

UPD. Estoy usando Lua con Corona SDK, si eso importa.

Respuesta

28

Hay una manera de deducir la "ruta local" de un archivo (más concretamente, la cadena que se usó para cargar el archivo).

Si requiere un archivo dentro lib.foo.bar, que podría estar haciendo algo como esto:

require 'lib.foo.bar' 

entonces se puede obtener la ruta de acceso al archivo que el primer elemento (y única) ... variables, cuando se están fuera de todas las funciones. En otras palabras:

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

Ahora, para obtener la "carpeta" debe eliminar el nombre del archivo. La forma más simple es usar match:

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

Y ahí lo tiene. Ahora se puede anteponer esa cadena a otros nombres de archivo y el uso que exigir:

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

Si se mueve alrededor bar.lua, folderOfThisFile se actualizarán automáticamente.

+0

Gracias, esto funcionó para cargar archivos. Pero cuando accedo a las propiedades públicas del módulo, aún necesito especificar la ruta completa (por ejemplo, 'lib.foo.bar.some_value'). – RocketR

+4

Eso no tiene nada que ver con la carga de archivos; simplemente refleja cómo ha elegido estructurar su Lua.Puede (por ejemplo) devolver una tabla en cada requerimiento y almacenarla en una var local: 'local baz = require (folderOfThisFile .. 'baz')' y luego hacer 'baz.some_value' – kikito

+1

Cool, no lo hice saber acerca de las funciones externas '...' siendo la cadena que se utilizó para requerir el archivo. –

13

Usted puede hacer

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

O

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

Entonces

-- 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

Extraño. Intenté cambiar 'package.path' y pensé que estaba haciendo algo mal porque dice' no field package.preload ['mylib-utils'] ',' no file './Mylib/mylib-utils.lua''. Pero estoy usando Lua dentro del SDK de Corona, tal vez tiene algunas peculiaridades con la carga de archivos. – RocketR

0

En el entorno de Conky's Lua he logrado incluir mi common.lua (en el mismo directorio) como require(".common"). Tenga en cuenta el carácter de punto ..

0

Estoy usando el siguiente fragmento de código. Debería funcionar tanto para archivos cargados con require, como para archivos llamados a través de la línea de comando. Luego use requireRel en lugar de require para aquellos que desea cargar con una ruta relativa.

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