2013-08-09 10 views
6

Nói rằng tôi có một dự án, có thư mục cấu hình như dưới đây:Cách sắp xếp đường dẫn mô-đun Lua và viết các cuộc gọi "yêu cầu" mà không mất tính linh hoạt?

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

mô hình/a.lua requries mô hình/b.lua: require "b"

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

main.lua tệp requries trong mô hìnhxem.


Bây giờ tôi gặp sự cố để tải các mô-đun này một cách chính xác. Tôi biết tôi có thể sửa chữa nó bằng cách thay đổi đòi hỏi các cuộc gọi đến:

mô hình/a.lua: require "model.b"

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

Nhưng nếu tôi làm điều đó, tôi phải sửa đổi các tệp này mỗi khi tôi thay đổi cấu trúc thư mục.

Vì vậy, câu hỏi của tôi là:

  1. Làm thế nào để khắc phục vấn đề con đường module mà không cần đường dẫn mã cứng trong các tập tin mô-đun?
  2. Tại sao Lua không sử dụng quy tắc tìm kiếm mô-đun của Node.js, trông dễ dàng hơn?

Trả lời

6

Khi bạn require một mô-đun, các tham số chuỗi từ require được thông qua vào các mô-đun mà bạn có thể truy cập bằng cách sử dụng cú pháp biến đối số .... Bạn có thể sử dụng điều này để bao gồm các mô-đun phụ thuộc khác nằm trong cùng một đường dẫn làm mô-đun hiện tại là require mà không làm cho mô-đun đó phụ thuộc vào tên mô-đun được mã hóa cố định.

Ví dụ của bạn, thay vì thực hiện:

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

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

Bạn có thể làm:

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

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

Bây giờ, nếu bạn thay đổi cấu trúc thư mục, ví dụ: di chuyển view đến một cái gì đó như control/subcontrol/foobar, sau đó control/subcontrol/foobar/a.lua (trước đây là view/a.lua) giờ sẽ cố gắng yêu cầu control/subcontrol/foobar/b.lua thay thế và "làm điều đúng".

Tất nhiên main.lua sẽ vẫn cần phải đủ điều kiện đường dẫn vì bạn cần một số cách để phân biệt giữa model/a.luaview/a.lua.

2

Cách khắc phục sự cố đường dẫn mô-đun mà không có đường dẫn mã cứng trong tệp mô-đun?

Tôi không có giải pháp đa nền tảng tốt hơn, có lẽ bạn nên lên kế hoạch cấu trúc thư mục sớm.

Tại sao Lua không sử dụng quy tắc tìm kiếm mô-đun của Node.js, trông dễ dàng hơn?

Vì Lua cố gắng hết sức để chỉ dựa vào ANSI C, thực sự thành công. Và trong ANSI C, không có khái niệm thư mục như vậy.

+1

Cảm ơn bạn đã chỉnh sửa và trả lời. Nhưng các dự án luôn luôn lớn từ nhỏ, và họ luôn luôn cần refactor. Thật khó để lập kế hoạch ở giai đoạn đầu.Khi không có sự phụ thuộc bên ngoài ngoại trừ ANSI C, tôi đồng ý đó là một lợi thế lớn. Nhưng điều này không xung đột với quy tắc tìm kiếm mô-đun di động hơn. – Chen

2

Có một số phương pháp bạn có thể sử dụng.

Bạn có thể thêm đường dẫn tương đối vào package.path như trong this SO answer. Trong trường hợp của bạn, bạn muốn thêm đường dẫn trong main.lua tương ứng với các cách khác nhau mà bạn có thể truy cập tệp. Điều này giữ tất cả các thay đổi cần thiết khi thay đổi cấu trúc thư mục của bạn cục bộ thành một tệp.

Bạn có thể thêm các đường dẫn tuyệt đối để package.path sử dụng debug.getinfo - điều này có thể là một chút dễ dàng hơn vì bạn không cần phải giải thích cho tất cả các truy cập tương đối, nhưng bạn vẫn cần phải làm điều này trong main.lua khi thay đổi cấu trúc thư mục của bạn, và bạn cần thực hiện thao tác chuỗi trên giá trị được trả về bởi debug.getinfo để tách tên mô-đun và thêm tên thư mục con.

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

Giải pháp là thêm thư mục main.lua (gốc dự án) vào package.path trong main.lua.

Một cách ngây thơ để hỗ trợ các thư mục trong tổng số 1 mức độ sâu:

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

Lưu ý cho require s trong (root dự án) sẽ xem xét các tập tin bên ngoài của gốc của dự án, mà không phải là mong muốn.

Một cách tốt hơn để sử dụng một số thư viện (ví dụ: paths, penlight) để giải quyết các đường dẫn tuyệt đối và thêm nó thay vì:

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

Sau đó, trong bạn nguồn sử dụng tên thư mục để phạm vi các tập tin :

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

-- view/a.lua 
require "view.b" 
Các vấn đề liên quan