How to require a file with a dot in the name? - lua

I am trying to require "config/lsp.rc.lua", but doing require("config.lsp.rc") gives an error.

The problem is simple: The responsible require loader will replace each dot with the directory separator (/ on Unix).
Note that you should not use / in require since it is a platform-specific directory separator (in practice it will be supported by Windows though).
Your best option would be to simply rename the file, replacing the dot with an underscore or the like to abide by Lua's conventions here.
However, if this is out of your control, you may also monkey-patch require to support your use case.
Instead of using . as directory separator, we may use /.
For that, we have to implement our own searcher:
Each entry in this table is a searcher function. When looking for a module, require calls each of these searchers in ascending order, with the module name (the argument given to require) as its sole argument. If the searcher finds the module, it returns another function, the module loader, plus an extra value, a loader data, that will be passed to that loader and returned as a second result by require. If it cannot find the module, it returns a string explaining why (or nil if it has nothing to say).
Luckily we can leverage package.searchpath to do most of the work for us:
local function searcher(module_name)
-- Use "/" instead of "." as directory separator
local path, err = package.searchpath(module_name, package.path, "/")
if path then
return assert(loadfile(path))
end
return err
end
Now we just have to pluck this into package.searchers for require to use it. We could insert it first, last, wherever, doesn't matter, so let's insert it last, such that only if all builtin searchers fail our searcher is tried:
table.insert(package.searchers, searcher)
Usage:
local lsp_rc = require("config/lsp.rc")
will then work as expected.
If you do not want to globally patch require, you could implement a local require that just searches in the Lua path, using your conventions:
local function myrequire(module_name)
return assert(loadfile(assert(package.searchpath(module_name, package.path, "/"))))
end
local lsp_rc = myrequire("config/lsp.rc")

Related

Require looks for .dll files instead of my modules?

So i've been trying to figure this out, im doing the following
main.lua:
package.path = io.popen("cd"):read'*all' -- to set the path the same as main.lua (for exporting)
local u = require("utilities") -- this is the line that dosent work
utilities.lua:
local u = {}
function u.GetService(s)
return require(tostring(s))
end
function u.Wait(s)
local ntime = os.clock() + s/10
repeat until os.clock() > ntime
end
function u.NPWait(s)
local ntime = os.time() + s
repeat until os.time() > ntime
end
return u
The error:
module 'utilities' not found:
Then here goes a search that DOES look in the correct folder, however it looks for .dll files
Require has never been something I've been good at, Sometimes I get it to work, sometimes it breaks like this, if someone can help me understand how to fix this then thank you, as this has been annoying me every so often
You're misunderstanding package.path.
Unlike the PATH variable used by windows and linux, in Lua you don't just tell it what directory to look in but also what the files should look like.
What you're doing is erasing the default search paths completely and replacing it with a broken path that won't find any files.
Generally speaking, to add a new directory to your path, you should add both C:\path\to\your\files\?.lua, and C:\path\to\your\files\?\init.lua, which are the two ways Lua loads modules by default.
You also shouldn't replace package.path, because you're keeping modules from being loaded elsewhere.
Your code should look somewhat like this:
local cd = io.popen("cd")
package.path = cd:read('*line') .. "\\?.lua;" .. package.path
cd:close()
The reason why it's still looking for DLL files is that package.cpath is separate, so you're not changing that.
require("utilities.lua") should work.
You have to specify how to get from the required name to the file. For example by adding a path and a file extension to it.
If you want to require c:\folder\script.lua with require("script") your package.path must contain something like c:\folder\?.lua where ? is replaced by the required name.
If you have your module in a folder with its name and let's say a init.lua for that module the path is c:\folder\?\init.lua
Just print the original package.path and see what's inside befor you overwrite it.
Refer to Lua Reference Manual 6.3 Modules: package.searchpath
A path is a string containing a sequence of templates separated by
semicolons. For each template, the function replaces each
interrogation mark (if any) in the template with a copy of name
wherein all occurrences of sep (a dot, by default) were replaced by
rep (the system's directory separator, by default), and then tries to
open the resulting file name.
For instance, if the path is the string
"./?.lua;./?.lc;/usr/local/?/init.lua" the search for the name foo.a will try to open the files ./foo/a.lua, ./foo/a.lc, and
/usr/local/foo/a/init.lua, in that order.

Lua require error if script is called "table.lua"?

Trying to replicate this simple Lua example (using the improved code in the second post), I encountered the following strange issue:
I copied the code verbatim, but happened to call the first file "table.lua" (instead of "funcs.lua").
The second file was called "main.lua" as in the example.
In my case, whatever I tried, I invariably got the popular error message "attempt to call field 'myfunc' (a nil value)" (as if the require statement had been ignored; but path etc. were all in order).
After two hours of trying and hunting for info, I more or less on a hunch renamed the first file from "table.lua" to "tabble.lua", and then everything promptly worked as expected. Renaming to e.g. "tables.lua" will also work.
Being very new to Lua, I'd still like to understand what exactly went wrong. Initially I thought the reason might be that "table" is a reserved Lua word, but all references I checked do not list it as such.
So what is going on here?
I am using LuaForWindows v5.1.4-46 with the included SciTE editor/IDE (v.1.75).
Thanks for all hints.
The standard libraries math, io, string, …, and table are pre-defined (and pre-loaded) in the Lua interpreter. Because require caches modules by name, saying require "table" will return the standard table library instead of loading your own table module from a file.
A good way to solve the problem is to create a folder and put your library files in there. If the folder is called mylib, then require "mylib.table" will work and load the file.
Alternatively, if you just need to load the file once and do not need the features of require (searching the file in a number of directories, caching loaded libraries), you can use loadfile: Change require "table" to loadfile "./table.lua" () (where ./table.lua should be the full (relative is fine) path to the file.)

Require custom C module in Lua by path

This is a problem that plagued me for quite a while.
After I wrote and compiled my custom functions into a shared library, require('mylib') would only work when the shared library was directly in the same directory as the script I called it from.
Any efforts to try require('/path/to/mylib') or similar absolute paths failed. Furthermore, "backtracking" through a relative path (i.e. using .. failed as well.
So how can one specify the bin directory, or wherever the shared library is output to?
Well according to the Lua documentation on the require call (using Lua 5.2 here), there are a few places the loader looks for these loadable modules.
It seems that require() uses what are called "searchers" (docs linked to in above) to determine where to find these modules. There are four searchers in total. From the docs:
The first searcher simply looks for a loader in the package.preload
table.
The second searcher looks for a loader as a Lua library, using the
path stored at package.path. The search is done as described in
function package.searchpath.
The third searcher looks for a loader as a C library, using the path
given by the variable package.cpath. Again, the search is done as
described in function package.searchpath. For instance, if the C path
is the string "./?.so;./?.dll;/usr/local/?/init.so" the searcher for module foo will try to open the files ./foo.so, ./foo.dll, and
/usr/local/foo/init.so, in that order. Once it finds a C library, this
searcher first uses a dynamic link facility to link the application
with the library. Then it tries to find a C function inside the
library to be used as the loader. The name of this C function is the
string "luaopen_" concatenated with a copy of the module name where
each dot is replaced by an underscore. Moreover, if the module name
has a hyphen, its prefix up to (and including) the first hyphen is
removed. For instance, if the module name is a.v1-b.c, the function
name will be luaopen_b_c.
The fourth searcher tries an all-in-one loader. It searches the C path
for a library for the root name of the given module. For instance,
when requiring a.b.c, it will search for a C library for a. If found,
it looks into it for an open function for the submodule; in our
example, that would be luaopen_a_b_c. With this facility, a package
can pack several C submodules into one single library, with each
submodule keeping its original open function.
The searcher of use to us is the third one: it is used for any shared libraries (.dll or .so) which is generally how our custom C modules are built.
Using the template string (the one with the question marks), the searcher will look in each of the specified paths, substituting the argument of require() in place of the question mark. In order to specify the path for this third searcher, one must set (or append to) package.cpath and then call require().
So perhaps you have a directory structure as
- ROOT
|-lua
|-bin
where lua contains script.lua and bin contains mylib.so
To load mylib.so, you just need these two lines of code in script.lua:
package.cpath = '/ROOT/bin/?.so;' .. package.cpath
libfuncs = require('mylib')
NOTE: Notice the semicolon. If you append (as opposed to the prepending above), make sure to lead with the semicolon on your added path. It is not there buy default. Otherwise your new path will be merged to the current default cpath, which is just ./?.so.
If you whant just configure your system to use some path to store
libraries there then best way just use LUA_PATH and LUA_CPATH env variables.
e.g.LUA_CPATH=/path/to/?.so. Or for specific Lua version like LUA_CPATH_5_3=/path/to/?.so.
But if you have full path to some library and whant just load this particular library from this directory you can use package.loadlib function.
local function loadlib(path, name)
local sep = string.sub(package.config, 1, 1)
local file = path .. sep .. name .. ((sep == '/') and '.so' or '.dll')
local func = 'luaopen_' .. name
local loader, msg = package.loadlib(file, func)
assert(loader, msg)
return assert(loader())
end
local mylib = loadlib([[/path/to]], 'mylib')

Accessing Lua Functions On Other Files

Hi I want to separate my Lua file into two files. One that holds my functions and one that can call them. I have done a lot of research on this and all the resources I find do not explain this process very indepth. They typically say to use:
require "subsystem.lua"
I put this at the top of a new Lua file that is saved to the same directory and am not able to access anything.
Is there a config file I need to modify? Where is it?
Require the module
The require function looks in a series of places to find a module. The exact list of places can be extensively customized by adjusting fields in the global table package.
The easiest way to get a sense of how many places and names it uses when looking for a module is to look at the error message produced when require fails. For example, on my PC, Lua 5.1 says this:
C:\Users\Ross>lua
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
> require "xyzzy"
stdin:1: module 'xyzzy' not found:
no field package.preload['xyzzy']
no file '.\xyzzy.lua'
no file 'C:\Program Files (x86)\Lua\5.1\lua\xyzzy.lua'
no file 'C:\Program Files (x86)\Lua\5.1\lua\xyzzy\init.lua'
no file 'C:\Program Files (x86)\Lua\5.1\xyzzy.lua'
no file 'C:\Program Files (x86)\Lua\5.1\xyzzy\init.lua'
no file 'C:\Program Files (x86)\Lua\5.1\lua\xyzzy.luac'
no file '.\xyzzy.dll'
no file '.\xyzzy51.dll'
no file 'C:\Program Files (x86)\Lua\5.1\xyzzy.dll'
no file 'C:\Program Files (x86)\Lua\5.1\xyzzy51.dll'
no file 'C:\Program Files (x86)\Lua\5.1\clibs\xyzzy.dll'
no file 'C:\Program Files (x86)\Lua\5.1\clibs\xyzzy51.dll'
no file 'C:\Program Files (x86)\Lua\5.1\loadall.dll'
no file 'C:\Program Files (x86)\Lua\5.1\clibs\loadall.dll'
stack traceback:
[C]: in function 'require'
stdin:1: in main chunk
[C]: ?
>
After looking internally, the first "real" place it looks for xyzzy is in the file named .\xyzzy.lua. Then it tries a number of folders and names in the folder where lua.exe was found. Finally, it looks for a DLL that might offer it. The list of folders it searches for a .lua file is controlled by the string value in package.path. (The comparable list for DLLs in is package.cpath.) In that value, require will replace each ? with the module name, and then attempt to read the file. The first one to succeed is used.
(The story here is slightly more complicated; you can create "searchers" that require will use to look in different places, and even change the order of the built-in searchers, but that is an advanced topic.)
So just putting modules in Lua files in the current directory should work just fine, and adjusting package.path before calling require for your own modules can cover most quirks you will encounter.
Create a module to require
At its simplest, a module is just something that can be stored in package.loaded. Which is what require will do with it once it has been found, so that multiple calls to require will only search once and always return the same value.
The traditional answer is for that "something" to be a table, usually mostly populated by functions that can be called, and occasionally having values. The math module is a good example: it provides lots of functions like sin and cos, along with the useful value math.pi and math.huge.
Aside from being stored in a table, there is nothing special about a function in a module. Like any other function, it takes parameters and return zero or more values. The only real rule is that a module should not change or add global variables.
So a very minimal module file can be as simple as:
return {
addtwo = function(a, b) return a+b end,
subtwo = function(x) return x-2 end,
}
which if stored as example.lua could be used like this:
local example = require "example"
print(example.addtwo(2,2)) -- 4
print(example.subtwo(42)) -- 40
A better module skeleton
Sticking all your code in a single table declaration will not fly for most real cases. It does not scale well, and it makes it difficult to clearly express the relationship among functions that share state.
-- simple modules
-- capture the name searched for by require
local NAME=...
-- table for our functions
local M = { }
-- A typical local function that is also published in the
-- module table.
local function addtwo(a,b) return a+b end
M.addtwo = addtwo
-- Shorthand form is less typing and doesn't use a local variable
function M.subtwo(x) return x-2 end
return M
Why no call to the module() function?
Lua 5.1 included a standard function named module() intended to be used at the top of module implementations. Its use was never required, and a consensus formed fairly quickly that it was not as helpful an idea as hoped. It has since been deprecated.
As a result, the simple skeleton I show above does not use it, and is portable to all versions of Lua since 5.1.
What you need to do is to return a table with the fields you want to access in subsystem.lua and then assign and use fields from that table in your main file. Something along these lines:
-- subsystem.lua
local function doSomething()
-- do something useful here
end
local function doMore()
-- do something else useful
end
return { doSomething = doSomething, doMore = doMore }
-- main.lua
local subsystem = require "subsystem" -- don't add `.lua` to your `require` call
subsystem.doSomething()
subsystem.doMore()
You may want to check Modules tutorial for details.
You probably want to use dofile instead of require.
dofile accepts file names, with paths.
require accepts module names and uses Lua search paths.

How to add function definition in Lua without requiring that a file be loaded?

I am using the C Fuzzy API and I want to load function module contained in a file lets say mycalculator.lua. This seem to run fine however when I later try to run another file A.lua that requires 'mycalculator' it does not work unless the mycalculator.lua file is available on the file system to reload. I am trying to just load it into the system and then have it available without having the mycalculator.lua in the file system. It there any way to have lua system keep the definition without loading it again? Basically I convert the mycalculator.lua into a string and then run it. I don't want to put mycalculator.lua file into the file system, I just want to hand it over as a string and then be able to require it in the next string I pass to the stack Thanks
There is a difference between simply executing a Lua script and loading a Lua module. If you wish to load a Lua module, then you must actually load a Lua module exactly as a script would: by calling require.
Since you appear to be new to Lua, I should probably explain this. You've probably seen code like this in Lua scripts:
require 'mycalculator'
That is not some special statement to Lua. That is a function call. It is just some syntactic sugar for:
require('mycalculator')
Functions in Lua can be called with NAME VALUE syntax instead of NAME(...) syntax, but it only allows you to send one parameter. And the parameter must be a literal (or table constructor).
In order to call the Lua require function from C, you must use the Lua stack. You must fetch the function from the global table by using lua_getfield(L, LUA_GLOBALSINDEX, "require"); Then, you push a string onto the stack containing the name of the module to load. Then, you use lua_pcall or whatever Lua function calling function to call it.

Resources