-
-
Notifications
You must be signed in to change notification settings - Fork 2
Listeners
Listeners (BETA) were introduced in v11.0.0. You create one in a plugin and then when it listens to the target, it runs the output.
Let's say we want to show a popup saying "Saved at PATH" everytime a user Saves As.
The syntax would therefore be:
my_listener = Listener(bytes("my_very_own_plugin", "utf-8"), save_as_file, my_already_defined_func)
- id: a unique ID for your listener. It should contain the name of your plugin and the version of it in order not to immitate an existing ID. This ID is compressed and then base64 encoded.
- target: this is the function you want to listen. This should be a WriterClassic function but in theory, you can use a function made by your plugin. It is out of this page's scope to explain how to do so.
- output: this is the function that runs when the target is detected. It can be a lambda.
There's another argument (condition
) which is optional and, by default, is set to a string containing True.
When the target is run, the output runs. However, if the condition is evaluated as False, it does not run.
The condition can access the WriterClassic globals as readonly and is re-evaluated each time the listener runs. This means you can work with variables that update in the condition argument.
With out new knowledge, let's add a condition.
Just to showcase it let's use random
. Of course you should do an actual condition though.
my_listener = Listener(bytes("my_very_own_plugin", "utf-8"), save_as_file, my_already_defined_func, "random.randint(0, 100) > 50")
Basically, we set so this listener only runs 50% of the times save_as_file
gets called.
Creating a Listener does not activate it... yet.
First, you must choose whether you want a BEFORE or AFTER Listener.
Before Listeners are run as soon as target runs.
After Listeners are run before the funtion ends.*
* IMPORTANT NOTE: sometimes, After Listeners are run much before the function ends. Unlike Before Listeners, After Listeners are more complex. Each function has its own approach when it comes to After Listeners. Certain functions support Before Listeners but not After Listeners.
In this case, let's use an After Listener.
Here's how to do it:
after_listeners.add_listeners({my_listener})
If you wanted to use a Before Listener, the variable would be before_listeners
and not after_listeners
.
Return Value | Meaning | Possible? |
---|---|---|
0 | Sucess! | Yes |
9 | Listener Subgroup Already Exists | No, as add_listeners checks for this condition |
10 | There's another Listener with the same ID | Yes |
Let's say you want to avoid the error code 10 from the previous code. One thing you can do is check if the ID is already taken.
Since there is no function for doing this operation, you can do the following workaround (which is what WriterClassic does internally):
if after_listeners.edit_listener(my_listener.listener_id, 4) == 2:
after_listeners.add_listeners({my_listener}) # yay, we can use this ID
else:
print('ID is taken.')
Why does this code work? Check the next heading so you understand.
This function is very powerful.
It can be used for thse main things:
- Verifying if an ID is taken
- Disabling a Listener
- Re-enabling a Listener
- Deleting a Listener for good
Here's an example that shows off all these features:
if after_listeners.edit_listener(my_listener.listener_id, 4) == 2:
after_listeners.add_listeners({my_listener}) # yay, we can use this ID
else:
print('ID is taken.')
quit()
input() # confirm before continuing
after_listeners.edit_listener(my_listener.listener_id, 1) # Out: 0
input() # confirm before re-enabling
after_listeners.edit_listener(my_listener.listener_id, 2) # Out: 0
input() # confirm before continuing
after_listeners.edit_listener(my_listener.listener_id, 7) # Out: 5
input() #
after_listeners.edit_listener(my_listener.listener_id, 3) # Out: the listener
print('Done!')
Long code, right?
We are gonna take a look at 2 things:
- Operation Types (the second argument of edit)
- Return Values
Operation Type | What does it do? |
---|---|
<1 | Verify ID and do nothing |
1 | Stop/disable Listener |
2 | Re-enable Listener |
3 | Delete Listener |
>3 | Verify ID and do nothing |
Anything other than an integer | Verify ID and do nothing |
Return Value | Meaning | Which operations might return it? |
---|---|---|
An instance of Listener()
|
Operation 3 was sucessful! | 3 |
0 | Sucess! | 1 and 2 |
2 | The ID could not be found. | Any |
3 | The Listener was already enabled. | 2 |
4 | The Listener was already disabled. | 1 |
5 | Invalid Operation Type* | Anything other than 1, 2 or 3 |
* NOTE: 5 only gets returned if the operation is invalid AND 2 wasn't returned before. This is the reason why you can use this function to verify if an ID exists.
Most times you don't want to do this as Listening Groups are ran automatically when the target is ran.
Let's say you want to run a Listening Group manually. For this exmaple, let's go back to our simple code.
my_listener = Listener(bytes("my_very_own_plugin", "utf-8"), save_as_file, my_already_defined_func)
if after_listeners.edit_listener(my_listener.listener_id, 4) == 2:
after_listeners.add_listeners({my_listener}) # yay, we can use this ID
else:
quit()
after_listeners.run_group(save_as_file)
And... BOOM! Our listener shall run.
This run function also has an optional argument: autopurge
. By default, it is True. Unless you have a real good reason, you want to keep this as True.
after_listeners.run_group(save_as_file, True) # keeping this as True
When AutoPurge is enabled, it gets rid of all the Listeners that are mal-functioning.
Return Value | Meaning | AutoPurge might be... |
---|---|---|
0 | Sucess! (No errors or purges) | True or False |
1 | Sucess! (Errors but no purges) | False |
6 | Tried to run the disabled group; not allowed. | True or False |
7 | The group does not exist. | True or False |
8 | Sucess! (Errors and purges) | True |
Let's say you want to remove a function from being listened (it can still be listened to later; this just gets rid of all listeners listening to it).
We can do it this way:
after_listeners.remove_group(save_as_file)
Done!
Return Value | Meaning |
---|---|
A set (type set ) containing several instances of Listener
|
Sucess! |
11 | The group does not exist. |
12 | Cannot remove the inactive group. (Only happens if you set group to the inactive group) |
If removing a single group isn't enough, you can remove ALL.*
* NOTE: all except the Inactive group.
The syntax is even simpler:
after_listeners.remove_all_groups() # no arguments needed
This will always return 0, meaning Sucess!
-
after_listeners
andbefore_listeners
are global WriterClassic variables; both are instances ofFunctionListeners()
- Even if the user quits your plugin, the function might still be cached. This is not very reliable, however. You should, instead, keep the plugin running. The way you do so is up to you.
- Pay attention that not all functions can be auto listenned to.
- It's, in theory, possible to do a workaround and get a circular listenning to work. However it will get the app into an infinite loop. Please don't do so.
WriterClassic Wiki
by MF366