import lua?

User avatar
Zaphob
Posts: 180
Joined: Wed May 09, 2012 8:07 am
Location: mg.mud.de

import lua?

Post by Zaphob »

Developers asked me, if it would be possible, or is it planned at all, to have a way to import lua files to Mudlet? They would like to code lua, but not bother with all the XML of Mudlet profile save files. It would be helpful to just import this from external lua files in the same directory, or something like that.

User avatar
Vadi
Posts: 5035
Joined: Sat Mar 14, 2009 3:13 pm

Re: import lua?

Post by Vadi »

Yeah, just have your script use dofile() or require().

User avatar
Oneymus
Posts: 321
Joined: Thu Sep 17, 2009 5:24 am

Re: import lua?

Post by Oneymus »

A little tip, if you'd like to use require() without jumping through too many hoops: modify package.path temporarily to include the directory where the code is stored. If you're installing your .lua files through the Package Manager, this would be the result of getMudletHomeDir().

For reference, this is how I handle package.path in Vyzor:
Code: [show] | [select all] lua
if not Vyzor then
	echo("Vyzor: Loading modules...\n")

	local path = package.path
	local homeDirectory = getMudletHomeDir():gsub("\\", "/")
	
	local luaDirectory = string.format("%s/%s", homeDirectory, [[?.lua]])
	local initDirectory = string.format("%s/%s", homeDirectory, [[?/init.lua]])
	package.path = string.format("%s;%s;%s", luaDirectory, initDirectory, path)

	local okay, content = pcall(require, "vyzor")
	package.path = path

	if okay then
		Vyzor = content
	else
		error(string.format("Vyzor: Error loading module: %s.\n", content))
	end

	if Vyzor then
		echo("Vyzor: Modules successfully loaded.\n")
	end

	tempTimer( 0, function () raiseEvent( "VyzorLoadEvent" ) end )
end
In fact, with the exception of test aliases, this is the only code for Vyzor that actually lives in Mudlet. The rest is written in a number of separate .lua files.

This snippet sits directly in a Mudlet Script, so it's called automatically on profile load.

User avatar
Belgarath
Posts: 232
Joined: Fri Jul 26, 2013 7:19 am
Discord: macjabeth#7149

Re: import lua?

Post by Belgarath »

Oneymus wrote:A little tip, if you'd like to use require() without jumping through too many hoops: modify package.path temporarily to include the directory where the code is stored. If you're installing your .lua files through the Package Manager, this would be the result of getMudletHomeDir().

For reference, this is how I handle package.path in Vyzor:
Code: [show] | [select all] lua
if not Vyzor then
	echo("Vyzor: Loading modules...\n")

	local path = package.path
	local homeDirectory = getMudletHomeDir():gsub("\\", "/")
	
	local luaDirectory = string.format("%s/%s", homeDirectory, [[?.lua]])
	local initDirectory = string.format("%s/%s", homeDirectory, [[?/init.lua]])
	package.path = string.format("%s;%s;%s", luaDirectory, initDirectory, path)

	local okay, content = pcall(require, "vyzor")
	package.path = path

	if okay then
		Vyzor = content
	else
		error(string.format("Vyzor: Error loading module: %s.\n", content))
	end

	if Vyzor then
		echo("Vyzor: Modules successfully loaded.\n")
	end

	tempTimer( 0, function () raiseEvent( "VyzorLoadEvent" ) end )
end
I'm sure there is a simple explanation for this, but I can't figure out why you put your raiseEvent inside a tempTimer (even though it's called instantly) instead of just calling it directly. Is there any difference?

Silvine
Posts: 142
Joined: Sat Oct 23, 2010 2:36 pm

Re: import lua?

Post by Silvine »

From memory tempTimer will run after the rest of the initialisation, so this guarantees that the Vyzor module will be loaded before VyzorLoadEvent is executed.
Mapper of Bedlam

User avatar
Oneymus
Posts: 321
Joined: Thu Sep 17, 2009 5:24 am

Re: import lua?

Post by Oneymus »

Silvine wrote:From memory tempTimer will run after the rest of the initialisation, so this guarantees that the Vyzor module will be loaded before VyzorLoadEvent is executed.
This is correct. Putting it in a tempTimer gives other Scripts a chance to execute, thus initializing other modules, before Vyzor raises its event. It takes script order out of the equation.

phasma
Posts: 191
Joined: Sat Aug 03, 2013 7:00 pm
Discord: phasma#4694

Re: import lua?

Post by phasma »

Yeah. We really need a better way to do things like this, but in the interim, it's a great hack.

User avatar
SlySven
Posts: 1019
Joined: Mon Mar 04, 2013 3:40 pm
Location: Deepest Wiltshire, UK
Discord: SlySven#2703

Re: import lua?

Post by SlySven »

Sounds like it is based off of Qt's C++ QTimer() in one-shot mode with a time interval of zero. Such a timer fires in the future when the event loop has done everything else that is waiting to be done - i.e. means "do this when you haven't got anything else left to do"! :geek:

User avatar
Zaphob
Posts: 180
Joined: Wed May 09, 2012 8:07 am
Location: mg.mud.de

Re: import lua?

Post by Zaphob »

Finally got around to working on this some more. The Vyzor example is really helpful for the overall structure and cleanliness in require()ing all the different .lua files for use in Mudlet. This is definitively beyond my lua skills as of now, so thanks again for the explanations.

While helpful, Vyzor has a different aim. It does not seem to use many triggers, aliases, timers, keys or scripts like my package does. So I was looking into commands to accomplish creating those objects for GUI view directly from the .lua files as well.

For example, I created this template for permAlias(name, parent, regex, lua code) to build an alias:
Code: [show] | [select all] lua
code_type = "alias"
code_name = "Test"
code_group = "Testgroup"
code_regex = "test"
code_string = [[--
echo("Test successful!")
]]

if exists(code_name, code_type) == 0 then
    permAlias(code_name, code_group, code_regex, code_string)
end
Only downside, I have a few aliases which use the "command" box, so I have to restructure a bit and put send(command) in the code box instead, as the permAlias() won't take input for the command box at all.

However there seem to be a few other limitations with current Mudlet commands' setup.

For example, I can only create groups with permGroup(name, itemtype) on root level, compare manual. How do I create groups of groups or even deeper levels?

For example, I can either create permRegexTrigger() or permSubstringTrigger with either one regex pattern or one substing pattern. But if I want to create one trigger with multiple patterns, maybe even mix regex and substring type, I did not find a command. Vadi suggested tempComplexRegexTrigger() maybe, but this would not be permanent and therefore not be visible for editing by the package's users in Mudlet GUI.

For example, there does not even seem to be a permScript() command to create Scripts objects this way. Which I would need because I sometimes use scripts to respond to events. Again Vadi suggested alternatively to put all scripting inside aliases, triggers, etc. or leave it invisible in GUI, handle all configuration in .lua files directly. Also I could register events from scripts with registerAnonymousEventHandler(event name, function name) - However again, this would be invisible in GUI and therefore not viewable nor adjustable by users.

One final issue I faced, but maybe already solved myself: The lua code that Mudlet will put inside the alias (trigger, etc) will have to be a string value like code_string in the example above. In effect, the code will not be as easy to handle by developers who edit the .lua files directly. Like we said in beginning, they want to be able to test and develop directly there without using Mudlet first. Now the solution would be to work with the following load() command in the .lua file for testing. I have to try it our some more but looks promising enough:
Code: [show] | [select all] lua
code_string = [[--
echo("Test successful!")
]]
my_test_function = load(code_string)
my_test_function()
-- output happens, or might happen if echo() was replaced with print()

-- another example to give and take arguments from loaded functions:
print(load("return ...")(1,2,3))
-- where 1, 2, 3 are arguments given to the function, which receives them in ...
-- this is called vararg function
Now to keep Vadi & the helpful team to the important work they are doing for the next Mudlet version as well, I want to ask here, is there any other feedback from other users, who considered the same path? Did I miss important functionality? Would you like more information about my findings as I go along? Cheers!

Jor'Mox
Posts: 1142
Joined: Wed Apr 03, 2013 2:19 am

Re: import lua?

Post by Jor'Mox »

permGroup is actually even less appealing than it seems, in that it doesn't actually create folders the way you would in the GUI. Rather, it creates blank triggers/aliases, et cetera, which it uses as groups. You can do the same thing with the relevant functions, and just give them blank pattern and code arguments. Which conveniently allows for the creation of nested "groups", but shares the downfall of the "groups" shows as regular things with errors, since you aren't supposed to have an alias or a trigger without a pattern.

Post Reply