How to organize the path of the Lua module and write “require” calls without losing flexibility?

Let's say I have a project whose folder structure looks below:

| main.lua | |---<model> // this is a folder | |a.lua | |b.lua | |---<view> |a.lua |b.lua 

model /a.lua requries model /b.lua : require "b"

view / a.lua requries view / b.lua : require "b"

main.lua requests files in the model and in the view .


Now I have a problem with loading these modules correctly. I know that I can fix this by changing the required calls to:

model / a.lua : require "model.b"

view / a.lua : require "view.b"

But if I do this, I have to change these files every time I change the folder structure.

So my questions are:

  • How to fix module path error without hard code paths in module files?
  • Why doesn't Lua use the Node.js module search rule, which looks simpler?
+6
source share
4 answers

When you require module, the string parameter from require is passed to the module, which you can access using the syntax of the argument variable ... You can use this to include other dependent modules that are on the same path as the current require ed module, without making it depend on the name of the hard coded module.

In your example, instead of executing:

 -- model/a.lua require "model.b" 

and

 -- view/a.lua require "view.b" 

You can do:

 -- model/a.lua local thispath = select('1', ...):match(".+%.") or "" require(thispath.."b") 

and

 -- view/a.lua local thispath = select('1', ...):match(".+%.") or "" require(thispath.."b") 

Now, if you change the directory structure, for example. move the view to something like control/subcontrol/foobar , then control/subcontrol/foobar/a.lua (formerly view/a.lua ) will now try to require control/subcontrol/foobar/b.lua instead and "do the right thing".

Of course, main.lua will still need to fully qualify the paths, since you need some way to eliminate the ambiguity between model/a.lua and view/a.lua .

+6
source

How to fix module path error without hard code paths in module files?

I don’t have the best cross-platform solution, maybe you should plan the folder structure at an early stage.

Why doesn't Lua use the Node.js module search rule, which looks simpler?

Because Lua is trying its best to rely only on ANSI C, which is really successful. And in ANSI C there is no such concept of directories.

+2
source

There are several approaches you can use.

You can add relative paths to package.path , as in this SO answer . In your case, you want to add paths to main.lua that correspond to different ways of accessing files. This saves all the changes necessary to change the directory structure in a single file.

You can add absolute paths to package.path with debug.getinfo - it might be a little easier since you do not need to take into account all the relative calls, but you still need to do this in main.lua when the directory structure changes, and you need perform string manipulations on the value returned by debug.getinfo to remove the module name and add subdirectory names.

 > lunit = require "lunit" > info = debug.getinfo(lunit.run, "S") > =info.source @/usr/local/share/lua/5.2/lunit.lua > =info.short_src /usr/local/share/lua/5.2/lunit.lua 
+2
source

The solution is to add the main.lua folder (project root) to the package.path in main.lua .

A naive way to support folders of the 1st level of depth:

 -- main.lua package.path = package.path .. ";../?.lua" 

Note for require in (project root) will look for files outside the project root, which is undesirable.

The best way to use some library (for example: paths , penlight ) is to allow an absolute path and add it instead:

 -- main.lua local projectRoot = lib.abspath(".") package.path = package.path .. ";" .. projectRoot .. "/?.lua" 

Then in the source, use the folder name for the file area:

 -- model/a.lua require "model.b" -- you can even do this require "view.b" 

and

 -- view/a.lua require "view.b" 
0
source

Source: https://habr.com/ru/post/951405/


All Articles