API for plugin framework in Lua - plugins

I am implementing a plugin system with Lua scripts for an application. Basically it will allow the users to extend the functionality by defining one or more functions in Lua. The plugin function will be called in response to an application event.
Are there some good open source plugin frameworks in Lua that can serve as a model?
In particular I wonder what is the best way to pass parameters to the plugin and receive the returned values, in a way that is both flexible and easy to use for the plugin writers.
Just to clarify, I am interested in the design of the API from the point of view of the script programming in Lua, not from the point of view of the hosting application.
Any other advice or best practices related to the design of a plugin system in Lua will be appreciated.

Lua's first-class functions make this kind of thing so simple that I think you won't find much in the way of frameworks. Remember that Lua's mantra is to provide minimal mechanism and let individual programmers work out policy for themselves.
Your question is very general, but here's what I recommend for your API:
A single plugin should be represented by a single Lua table (just as a Lua module is represented by a single table).
The fields of the table should contain operations or callbacks of the table.
Shared state should not be stored in the table; it should be stored in local variables of the code that creates the table, e.g.,
local initialized = false
return {
init = function(self, t) ... ; initialized = true end,
something_else = function (self, t)
if not initialized then error(...) end
...
end,
...
}
You'll also see that I recommend all plugin operations use the same interface:
The first argument to the plugin is the table itself
The only other argument is a table containing all other information needed by the operation.
Finally, each operation should return a result table.
The reason for passing and returning a single table instead of positional results is that it will help you keep code compatible as interfaces evolve.
In summary, use tables and first-class functions aggressively, and protect your plugin's private state.

The plugin function will be called in response to an application event.
That suggests the observer pattern. For example, if your app has two events, 'foo' and 'bar', you could write something like:
HostApp.listeners = {
foo = {},
bar = {},
}
function HostApp:addListener(event, listener)
table.insert(self.listeners[event], listener)
end
function HostApp:notifyListeners(event, ...)
for _,listener in pairs(self.listeners[event]) do
listener(...)
end
end
Then when the foo event happens:
self:notifyListeners('foo', 'apple', 'donut')
A client (e.g. a plugin) interested in the foo event would just register a listener for it:
HostApp:addListener('foo', function(...)
print('foo happened!', ...)
end)
Extend to suit your needs.
In particular I wonder what is the best way to pass parameters to the plugin and receive the returned values
The plugin just supples you a function to call. You can pass any parameters you want to it, and process it's return values however you wish.

Related

Visual Studio Code Providers for language extension

I am trying to learn how to implement some of the helper providers: autocomplete, signature help and hover.
I am doing it for a framework that, as far as I know, it cannot be executed outside its main application, so one way I thought to go about this (get the objects types, methods and docs) is by parsing its documentation.
For example the Hover provider; once the cursor is hovering the word, I can search for it in the documentation and display the result:
class HSHoverProvider implements vscode.HoverProvider {
public provideSignatureHelp(
document: vscode.TextDocument,
position: vscode.Position,
token: vscode.CancellationToken
): vscode.SignatureHelp {
// get current word/line under the cursor and find a match inside the docs
...
return new vscode.Hover(data);
}
}
...
context.subscriptions.push(
vscode.languages.registerHoverProvider("lua", new HSHoverProvider())
);
This works fine when the action is directly on the initial declaration. I can parse directly the line and find what I need with a regex.
-- hovering over `application`, I check the context with a regex.
local app = hs.application('Code')
However, I am having a hard time when it comes to a "reference". Searching the document for the declaration of app with a regex approach leads to many edge cases, mainly because of the declaration scope:
Example:
-- declaration target
local app = hs.application('Code')
local function foo()
local app = hs.pasteboard()
end
local function bar()
if 'foo' then
local app = hs.alert()
end
do local app = hs.window.focusedWindow() end
-- a regex will have a hard time to understand which declaration is correct
print(app:title())
end
This lead me thinking that a regex is not the appropriate solution. I also thought that implementing vscode.DefinitionProvider will give me some insight but it did not.
I've tried to look at other extensions that do already the same thing (mainly Lua Language Server by sumneko), but I am not able to understand how they went for it (besides they are using the language server approach).
How would I go for something like this? Do I need an AST tree and inspect from there? Would using the language server be a better choice? Am I missing a bigger picture or I just need a more robust document parser?
Any insight is appreciated. Thanks in advance
The usual approach in such cases is to create a symbol table. You start by parsing the code for which you want to provide the tooling. From the parse tree (or syntax tree, depending on the parser tool used) you generate your symbol table, which holds the informations you need, including the nesting of blocks and symbols, the type of symbols (e.g. object name or object reference) and the scope for which a symbol is valid.

is there any way to iterate two lists parallely in sightly?

Consider this code in java
for(int i=0,j=0;i<list1.size() && j<list2.size();i++,j++){
//do something
}
Can we do the similar thing in sightly? I tried best on my level but I couldn't find a way to do it. Please help on this.
There is no support for this kind of iteration and this is intended (in order to avoid putting your business logic in the HTL/Sightly template). You should instead invoke an Use-Api object which applies this logic and returns a collection of tuples from the two lists.
Adding to the answer posted by Vlad, You could either use
Sling Models
WCMUse class
server side javascript to perform such business logic
I would say it is better to use nodejs for such simple problems as it is more productive, easy to write and lives in the same folder as the sightly/HTL code.
For example, if your component name is 'componentA'
your HTL/sightly code is componentA.html residing inside componentA folder
and your business logic can be componentA.js residing in the same folder.
use(function() {
/*
Business logic
*/
return {
name: valueName,
list: listObject
};
});
Sling Models are very effective when you need to perform business logic using injected properties and resources. For example, a component that has several primitive and derived (from resource) properties.

zend framework own functions and classes

Now I have some experience in using the Zend Framework. I want to go deeper in the topic and rewrite some old php projects.
What is the best place to save own functions and classes?
And how do I tell Zend where they are? Or is there already a folder for own stuff? May I have different folders for different files?
For example I want to save a php document with the name math_b.php which includes several special functions to calculate and another one date_b.php which has abilities for datetime stuff. Is that possible or shall I have different files for every function?
I would also like to reuse the functions in other projects and then just copy the folders.
There is no single "right" answer for this. However, there are several general guidelines/principles that I commonly employ.
Do not pollute global scope
Namespace your code and keep all functions is classes. So, rather than:
function myFunction($x) {
// do stuff with $x and return a value
}
I would have:
namespace MyVendorName\SomeComponent;
class SomeUtils
{
public static function myFunction($x)
{
// do stuff with $x and return a value
}
}
Usage is then:
use MyVendorName\SomeComponent\SomeUtils;
$val = SomeUtils::myFunction($x);
Why bother with all this? Without this kind of namespacing, as you bring more code into your projects from other sources - and as you share/publish your code for others to consume in their projects - you will eventually encounter name conflicts between their functions/variables and yours. Good fences make good neighbors.
Use an autoloader
The old days of having tons of:
require '/path/to/class.php';
in your consumer code are long gone. A better approach is to tell PHP - typically during some bootstrap process - where to find the class MyVendor\MyComponent\MyClass. This process is called autoloading.
Most code these days conforms to the PSR-0/PSR-4 standard that maps name-spaced classnames to file-paths relative to a file root.
In ZF1, one typically adds the ./library folder to the PHP include_path in ./public/index.php and then add your vendor namespace into the autoloaderNameSpaces array in ./application/config.ini:
autoloaderNameSpaces[] = 'MyVendor';
and places a class like MyVendor\MyComponent\MyClass in the file:
./library/MyVendor/MyComponent/MyClass.php
You can then reference a class of the form MyVendor\MyComponent\MyClass simply with:
// At top of consuming file
use MyVendor\MyComponent\MyClass;
// In the consuming page/script/class.
$instance = new MyClass(); // instantiation
$val = MyClass::myStaticMethod(); // static method call
Determine the scope of usage
If I have functionality is required only for a particular class, then I keep that function as a method (or a collection of methods) in the class in which it is used.
If I have some functionality that will be consumed in multiple places in a single project, then I might break it out into a single class in my own library namespace, perhaps MyVendor.
If I think that a function/class will be consumed by multiple projects, then I break it out into its own project with its own repo (on Github, for example), make it accessible via Composer, optimally registering it with Packagist, and pay close attention to semantic versioning so that consumers of my package receive a stable and predictable product.
Copying folders from one project into another is do-able, of course, but it often runs into problems as you fix bugs, add functionality, and (sometimes) break backward-compatibility. That's why it is usually preferable to have those functions/classes in a separate, semantically-versioned project that serves as a single source-of-truth for that code.
Conclusion
Breaking functionality out into separate, namespaced classes that are autoloaded in a standard way gives plenty of "space" in which to develop custom functionality that is more easily consumed, more easily re-used, and more easily tested (a large topic for another time).

MATLAB doesn't show help for user-created class private methods and properties

This is the problem:
Create a class and set the access to be private for some of the properties or methods.
Use the doc command for the created class. This will auto-generate documentation from your comments and show it in the built-in help browser.
doc classname
The problem is that documentation for the private properties and methods is not shown in the help browser. Is there any way to overcome this problem?
So I spent like 10 minutes using the debugger, jumping from one function to the next, tracing the execution path of a simple doc MyClass call.
Eventually it lead me to the following file:
fullfile(toolboxdir('matlab'),'helptools','+helpUtils','isAccessible.m')
This function is called during the process of generating documentation for a class to determine if the class elements (including methods, properties, and events) are publicly accessible and non-hidden. This information is used later on to "cull" the elements.
So if you are willing to modify MATLAB's internal functions, and you want the docs to always show all methods and properties regardless of their scope, just rewrite the function to say:
function b = isAccessible(classElement, elementKeyword)
b = true;
return
% ... some more code we'll never reach!
end
Of course, don't forget to make a backup of the file in case you changed your mind later :)
(on recent Windows, you'll need to perform this step with administrative privileges)
As a test, take the sample class defined in this page and run doc someClass. The result:
This behaviour is by design - the auto-generated documentation is intended for users of the class, who would only be able to access the public properties and methods.
There's no way that I'm aware of to change this behaviour.
You could try:
Use an alternative system of auto-generating documentation such as this from the MATLAB Central File Exchange (which I believe will document all properties, not just public).
Implement your own doc command. Your doc command should accept exactly the same inputs as the built-in doc command, detect if its inputs correspond to your class/methods/properties etc, and if so display their documentation, otherwise pass its inputs straight through to the built-in doc. Make sure your command is ahead of the built-in on the path.

What is to prefer in Restlet: handleGet, handlePost OR represent, acceptRepresetation?

IMHO, there are two techiques to handle a query for a resource:
For http GET you can override represent(Variant variant) or handleGet().
For http POST the same applies with acceptRepresentation(Representation entity) and handlePost().
The doc for handleGet says:
Handles a GET call by automatically returning the best representation available. The content negotiation is automatically supported based on the client's preferences available in the request. This feature can be turned off using the "negotiateContent" property.
and for represent:
Returns a full representation for a given variant previously returned via the getVariants() method. The default implementation directly returns the variant in case the variants are already full representations. In all other cases, you will need to override this method in order to provide your own implementation.
What are the main differences between these two types of implementations? In which case should I prefer one over the other? Is it right that I can achieve with e.g. handleGet() everything that would work with represent()?
I first started using handleGet setting the entity for the response. When I implemented another project I used represent. Looking back i can't really say one way is better or clearer than the other. What are your expirences for that?
I recommend using represent(Variant) because then you’ll be leveraging the content negotiation functionality provided by the default implementation of handleGet(Request, Response).
BTW, lately I've started using the annotation-based syntax instead of overriding superclass methods, and I like it. I find it clearer, simpler, and more flexible.
For example:
#Post('html')
Representation doSearch(Form form) throws ResourceException {
// get a field from the form
String query = form.getFirstValue("query");
// validate the form - primitive example of course
if (query == null || query.trim().length() == 0)
throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST, "Query is required.");
// do something
SearchResults searchResults = SearchEngine.doSearch(query);
// return a HTML representation
return new StringRepresentation(searchResults.asHtmlString(), MediaType.TEXT_HTML);
}
The advantages of using this approach include the incoming representation being automatically converted to a useful form, the method can be named whatever makes sense for your application, and just by scanning the class you can see which class methods handle which HTTP methods, for what kind of representations.