ClipShare Rule Lua Script Guide(Not yet released)
Tip
This document applies to ClipShare version 1.5.0 and later(Not yet released).
This document explains how to write Lua scripts for ClipShare rule management, what can and cannot be used, and the input/output format of scripts.
This script environment is not a full Lua 5.4 runtime. It runs inside a sandboxed environment with restrictions. Please follow this document when writing scripts and do not assume that every Lua standard library is available.
1. Use Cases
When regular-expression rules are not enough and more complex logic is required, you can use Lua script rules.
Typical scenarios:
- Multi-condition checks based on content
- Extracting content and then processing it again
- Dynamically generating tags
- Deciding whether to block sync based on content type
- Combining notification title, source, tags, and other context for judgments
2. Execution Model
Each script rule executes a Lua function when triggered. The function receives one parameter: params.
You need to return a Lua table as the processing result.
If the script execution fails, the rule will not get a valid result.
Important:
paramsis implicitly available
Although the runtime always passes a fixed params argument internally, params is already directly available when you write the script. You do not need to declare the function entry yourself.
That means you should write the script logic directly, for example:
local content = params.content or ""
return {
title = params.title,
content = content,
extractedContent = params.extractedContent,
tags = params.tags or {},
isSyncDisabled = params.isSyncDisabled or false,
isDropped = false,
isFinalRule = false,
}Do not write it like this:
function main(params)
...
endAnd do not write it like this either:
return function(params)
...
endYou only need to write the script body directly and return the result table at the end.
3. Input Parameter params
The script always receives one fixed parameter:
paramsAvailable fields:
| Field | Type | Description |
|---|---|---|
params.type | string | Content type, possibly text, image, sms, or notification |
params.source | string? | Content source, possibly a local path or an app package name |
params.title | string? | Notification title; usually only present for notification content |
params.content | string | Original content |
params.extractedContent | string? | Previously extracted content |
params.tags | table? | Existing tag list |
params.isSyncDisabled | bool? | Whether sync has already been marked as blocked |
Important:
?after a type means nullable
If a field type ends with ?, it means the field may be nil, in other words, it may have no value.
It is recommended to handle nullability before using such fields, otherwise the script may fail.
Two common ways to handle it:
- Explicitly check whether it is nil
if params.title ~= nil then
print(params.title)
end- Use
orto provide a default value
local title = params.title or ""
local tags = params.tags or {}
local isSyncDisabled = params.isSyncDisabled or falseIf you are not sure whether a field may be nil, prefer giving it a default value with or.
4. Return Result
The script must return a table. It is recommended to always return a complete structure:
return {
title = params.title,
content = params.content,
extractedContent = params.extractedContent,
tags = params.tags or {},
isSyncDisabled = params.isSyncDisabled or false,
isDropped = false,
isFinalRule = false,
}Field descriptions:
| Field | Type | Description |
|---|---|---|
title | string? | Title after processing, mainly used for notification content |
content | string | Content after processing |
extractedContent | string? | Extracted content after processing |
tags | table | Tag list after processing |
isSyncDisabled | bool | Whether sync should be blocked |
isDropped | bool | Whether this content should be dropped |
isFinalRule | bool | Whether to stop subsequent rules |
5. ClipShare Global Functions and Objects
The following items are not part of the Lua standard library. They are global functions and objects injected by ClipShare into the Lua sandbox environment while the rule script runs.
You can think of them as helper capabilities specifically provided by ClipShare for rule scripts.
They are mainly used for:
- Reading runtime information provided by ClipShare
- Outputting debug logs
- Sending notifications
- Calling some platform-related capabilities
- Performing common encoding, decoding, and digest calculations
If you want to implement custom rule logic, you will usually use both basic Lua syntax and the global functions/objects listed here.
5.1 log Debug Logs
Used to output debug logs:
log.debug("message")
log.info("message")
log.warn("message")
log.error("message")Parameter description:
| Function | Parameters | Purpose |
|---|---|---|
log.debug(message) | message: string | Output a debug log |
log.info(message) | message: string | Output an info log |
log.warn(message) | message: string | Output a warning log |
log.error(message) | message: string | Output an error log |
5.2 print Quick Debug Output
This is a quick debug function, equivalent to outputting a debug log.
Equivalent to:
log.debug(...)It is suitable for quick debugging.
5.3 json JSON Encoding and Decoding
Used for JSON encoding and decoding.
json.encode(value)
json.decode(text)Parameter description:
| Function | Parameters | Return Value | Purpose |
|---|---|---|---|
json.encode(value) | value: table | string | Encode a Lua table into a JSON string |
json.decode(text) | text: string | table | Parse a JSON string into a Lua table |
5.4 notify Send Notification
Used to actively send an app notification from the script.
Send a notification:
notify(title, content)Parameter description:
| Function | Parameters | Purpose |
|---|---|---|
notify(title, content) | title: string, content: string | Send an app notification |
5.5 ContentType Content Type
Represents the type of the current content.
Available enum values:
ContentType.text
ContentType.image
ContentType.sms
ContentType.notificationValue descriptions:
| Value | Description |
|---|---|
| ContentType.text | Text |
| ContentType.image | Image |
| ContentType.sms | SMS |
| ContentType.notification | Notification |
5.6 Platform Platform Information
Represents the platform where the current script is running.
Platform info:
Platform.isAndroid
Platform.isIOS
Platform.isWindows
Platform.isMacOS
Platform.isLinuxValue descriptions:
| Value | Description |
|---|---|
| Platform.isAndroid | Whether the platform is Android |
| Platform.isIOS | Whether the platform is iOS |
| Platform.isWindows | Whether the platform is Windows |
| Platform.isMacOS | Whether the platform is MacOS |
| Platform.isLinux | Whether the platform is Linux |
5.7 self Current Device Information
Represents information about the current device itself.
Current device info:
self.devId
self.devNameValue descriptions:
| Value | Description |
|---|---|
| devId | Local device id |
| devName | Local device name |
5.8 app App Version Information
Represents version information about the current ClipShare app itself.
App version info:
app.versionName
app.versionNumberValue descriptions:
| Value | Description |
|---|---|
| versionName | ClipShare version name, such as 1.4.3 |
| versionNumber | ClipShare version number, such as 25 |
5.9 android Android Extension Capabilities
Represents extension capabilities available on the Android platform.
Android-only capabilities:
android.notifyMediaScan(imagePath)
android.toast(content)
android.sendHistoryChangedBroadcast(type, content, from_dev_id, from_dev_name)Parameter description:
| Function | Parameters | Purpose |
|---|---|---|
android.notifyMediaScan(imagePath) | imagePath: string | Notify the Android media library to scan the specified file, usually for images or media files |
android.toast(content) | content: string | Show a Toast on Android |
android.sendHistoryChangedBroadcast(type, content, from_dev_id, from_dev_name) | type: ContentType, content: string, from_dev_id: string, from_dev_name: string | Send a history-changed broadcast |
5.10 crypto Digest Calculation
Used to calculate common digest values.
crypto.calcMD5(content)
crypto.calcSHA1(content)
crypto.calcSHA256(content)Parameter description:
| Function | Parameters | Return Value | Purpose |
|---|---|---|---|
crypto.calcMD5(content) | content: string | string | Calculate MD5 |
crypto.calcSHA1(content) | content: string | string | Calculate SHA-1 |
crypto.calcSHA256(content) | content: string | string | Calculate SHA-256 |
5.11 base64 Base64 Encoding and Decoding
Used for Base64 encoding and decoding.
base64.encode(content)
base64.decode(content)Parameter description:
| Function | Parameters | Return Value | Purpose |
|---|---|---|---|
base64.encode(content) | content: string | string | Encode a string to Base64 |
base64.decode(content) | content: string | string | Decode a Base64 string |
5.12 regex Regular Expression
Note: Lua itself provides pattern matching (
string.match/findwith Lua patterns), not the regular expressions people usually mean. If you need standard regex support, use the injectedregexhere.
Used for regex matching.
regex.match(content, pattern, caseSensitive, multiLines, dotAll)
regex.matchGroups(content, pattern, caseSensitive, multiLines, dotAll)Parameters:
| Parameter | Type | Purpose |
|---|---|---|
content | string | Original text to be matched |
pattern | string | Regular expression pattern |
caseSensitive | bool | Whether matching is case-sensitive |
multiLines | bool | Whether multi-line mode is enabled (anchors match by line) |
dotAll | bool | Whether . matches newlines |
Function return values:
| Function | Return Value | Description |
|---|---|---|
regex.match(content, pattern, caseSensitive, multiLines, dotAll) | table | Returns a list of all full matches (group 0), indexed from 1. Returns an empty table if no match exists |
regex.matchGroups(content, pattern, caseSensitive, multiLines, dotAll) | table | Returns a 2D list of capture groups for all matches (group 1..N only, excluding group 0). Returns an empty table if no match exists |
Return value examples:
-- regex.match(...)
{ "abc123", "xyz456" }
-- regex.matchGroups(...)
{
{ "abc", "123" },
{ "xyz", "456" }
}5.13 Async Wrapper
The script environment has already wrapped an async helper based on Lua coroutines: lua-async-await
The following methods are globally exposed in scripts:
| Method | Example | Description |
|---|---|---|
task.create() | local awaiter = task.create() | Create an awaiter that can be waited for by await |
async | async(function() end) | Wrap a method as an async method |
await | local result = await(awaiter) | Asynchronously wait for an awaiter and get its result |
5.14 HTTP Requests
HTTP methods based on Dio:
http.getAsync(url, options)
http.postAsync(url, options, body)
http.putAsync(url, options, body)
http.deleteAsync(url, options, body)| Parameter | Type | Description |
|---|---|---|
url | string | HTTP request URL |
options | table | HTTP request header parameters |
body | string? or table? | HTTP request body |
Request return value:
| Parameter | Type | Description |
|---|---|---|
ok | bool | Whether the request succeeded. true means success, false means failure |
statusCode | number? | HTTP status code. Present only when the request succeeds, or when it fails with a DioException |
statusMessage | string? | HTTP status message. Present only when the request succeeds, or when it fails with a DioException |
headers | table? | Response headers. Present only when the request succeeds |
body | string? | Response body. Present only when the request succeeds |
message | string? | Dart-layer Error exception message. Present only when the request fails and the exception is not a DioException |
HTTP GET request example:
local function fetchBaiduAsync()
local awaiter = http.getAsync('https://baidu.com', {})
local result = await(awaiter)
print(result.statusCode) -- Output 200
return result
end
local baidu = await(fetchBaiduAsync())
print(baidu.ok) -- Output trueNote: If you return an async method from a module, wrap it with async when returning:
local function fetchBaidu()
local awaiter = http.getAsync('https://baidu.com', {})
local result = await(awaiter)
print(result.statusCode)
return result
end
return {
fetchBaiduAsync = async(fetchBaidu)
}6. Lua Version and Sandbox Restrictions
The current rule script runtime is based on Lua 5.4.8.
You can generally assume common basic syntax, control flow, local variables, functions, and most common standard-library features are still available, but this is not a complete, unrestricted Lua environment.
The available built-in Lua libraries and capabilities are:
pcall/xpcall- protected callstonumber/tostring- type conversiontype- get the typeselect- select argumentsunpack(compatible withtable.unpack) - unpack arraysipairs/pairs- iterate arrays/tablesnext- get the next key-value pairmath- full math librarytable- full table librarystring- full string librarycoroutine- full coroutine libraryutf8- UTF-8 supportos.clock()- CPU timeos.date()- date formattingos.time()- timestampos.difftime()- time difference calculation_VERSION- Lua version stringprint- already redirected tolog.debug(log output)
7. Writing Recommendations
- Prefer keeping the returned structure complete
- When the logic becomes complex, store intermediate results in local variables first
- Use
log.debugorprintto help with debugging - Try not to modify global variables that are not documented here
- Do not depend on dangerous capabilities that are not explicitly documented here
8. Example: Extract Verification Codes from SMS/Text and Add a Tag
Here is a common example: first check whether the content contains the verification code keyword. If it does, extract the first group of 4 to 6 consecutive digits and add the tag Verification Code.
Note that Lua uses its own pattern matching syntax. The example script below uses the injected regex standard regex support instead.
Example content:
[Some Service] Your verification code is 123456. It is valid for 5 minutes. Please do not share it with others.Click to expand the example script
-- Read the original content
local content = params.content or ""
-- First check whether the content contains the "verification code" keyword (using regex.match)
local keywordMatches = regex.match(content, "verification code.*", false, false, false)
local hasCodeKeyword = #keywordMatches > 0
-- Only when the keyword is matched, extract the first group of 4 to 6 consecutive digits
local code = nil
if hasCodeKeyword then
-- Directly match 4 to 6 digits and take the first result
local codeMatches = regex.match(content, "\\d{4,6}", true, false, false)
code = codeMatches[1]
end
-- Copy the tag list to avoid directly depending on nil
local tags = params.tags or {}
-- Add the tag only when the keyword is matched and the code is extracted successfully
if hasCodeKeyword and code then
table.insert(tags, "Verification Code")
end
-- Return the processed rule result
return {
-- Notification titles usually keep the original value
title = params.title,
-- Keep the original content unchanged
content = content,
-- Return the extracted verification code as extractedContent
extractedContent = code,
-- Return the updated tag list
tags = tags,
-- Do not block sync
isSyncDisabled = params.isSyncDisabled or false,
-- Do not drop the content
isDropped = false,
-- Do not stop subsequent rules
isFinalRule = false,
}10. Asking AI
The following text can be sent directly to AI to generate Lua scripts suitable for ClipShare rules.
ClipShare Rule Lua Script Generation Prompt:
Click to expand and view
You are writing a Lua script for the ClipShare rule system.
This is not a full Lua runtime. It is a restricted sandbox environment. The generated code must strictly follow the constraints below, and you must not assume that all Lua standard libraries are available.
## 1. Script Input
The script already has one implicitly provided parameter:
```lua
params
```
`params` can be used directly in the script body. You do not need to, and must not, declare a function entry.
Incorrect:
```lua
function main(params)
...
end
```
Incorrect:
```lua
return function(params)
...
end
```
The correct approach is to write the script body directly and return a result table at the end.
Available fields:
| Field | Type | Description |
|---|---|---|
| `params.type` | `string` | Content type, possibly `text`, `image`, `sms`, or `notification` |
| `params.source` | `string?` | Content source, possibly a local path or an app package name |
| `params.title` | `string?` | Notification title; usually only present for notification content |
| `params.content` | `string` | Original content |
| `params.extractedContent` | `string?` | Previously extracted content |
| `params.tags` | `table?` | Existing tag list |
| `params.isSyncDisabled` | `bool?` | Whether sync has already been marked as blocked |
`?` after a type means that the field may be `nil`; handle nullability before using it.
Common handling patterns:
```lua
if params.title ~= nil then
print(params.title)
end
```
Or:
```lua
local title = params.title or ""
local tags = params.tags or {}
local isSyncDisabled = params.isSyncDisabled or false
```
If you are not sure whether a field may be nil, prefer using `or` to provide a default value.
## 2. Script Return Value
The script must return a Lua table. It is recommended to always return a complete structure:
```lua
return {
title = params.title,
content = params.content,
extractedContent = params.extractedContent,
tags = params.tags or {},
isSyncDisabled = params.isSyncDisabled or false,
isDropped = false,
isFinalRule = false,
}
```
Field meanings:
| Field | Type | Description |
|---|---|---|
| `title` | `string?` | Title after processing, mainly used for notification content |
| `content` | `string` | Content after processing |
| `extractedContent` | `string?` | Extracted content after processing |
| `tags` | `table` | Tag list after processing |
| `isSyncDisabled` | `bool` | Whether sync should be blocked |
| `isDropped` | `bool` | Whether this content should be dropped |
| `isFinalRule` | `bool` | Whether to stop subsequent rules |
## 3. ClipShare Global Functions and Objects
The following items are not part of the Lua standard library. They are global functions and objects injected by ClipShare into the Lua sandbox environment while the rule script runs.
### 1. `log` Debug Logs
```lua
log.debug("message")
log.info("message")
log.warn("message")
log.error("message")
```
### 2. `print` Quick Debug Output
`print(...)` has already been redirected to `log.debug(...)`, and is suitable for quick debugging.
### 3. `json` JSON Encoding and Decoding
```lua
json.encode(value)
json.decode(text)
```
- `json.encode(value: table) -> string`
- `json.decode(text: string) -> table`
### 4. `notify` Send Notification
```lua
notify(title, content)
```
- `notify(title: string, content: string)`: send an app notification
### 5. `ContentType` Content Type
```lua
ContentType.text
ContentType.image
ContentType.sms
ContentType.notification
```
### 6. `Platform` Platform Information
```lua
Platform.isAndroid
Platform.isIOS
Platform.isWindows
Platform.isMacOS
Platform.isLinux
```
### 7. `self` Current Device Information
```lua
self.devId
self.devName
```
- `self.devId`: local device id
- `self.devName`: local device name
### 8. `app` App Version Information
```lua
app.versionName
app.versionNumber
```
- `app.versionName`: ClipShare version name, such as `1.4.3`
- `app.versionNumber`: ClipShare version number, such as `25`
### 9. `android` Android Extension Capabilities
```lua
android.notifyMediaScan(imagePath)
android.toast(content)
android.sendHistoryChangedBroadcast(type, content, from_dev_id, from_dev_name)
```
- `android.notifyMediaScan(imagePath: string)`: notify the Android media library to scan the specified file, usually for images or media files
- `android.toast(content: string)`: show a Toast on Android
- `android.sendHistoryChangedBroadcast(type: ContentType, content: string, from_dev_id: string, from_dev_name: string)`: send a history-changed broadcast
### 10. `crypto` Digest Calculation
```lua
crypto.calcMD5(content)
crypto.calcSHA1(content)
crypto.calcSHA256(content)
```
- `crypto.calcMD5(content: string) -> string`
- `crypto.calcSHA1(content: string) -> string`
- `crypto.calcSHA256(content: string) -> string`
### 11. `base64` Base64 Encoding and Decoding
```lua
base64.encode(content)
base64.decode(content)
```
- `base64.encode(content: string) -> string`
- `base64.decode(content: string) -> string`
### 12. `regex` Regular Expression
Lua itself provides pattern matching, not standard regular expressions. If you need standard regex support, use the injected `regex` here.
```lua
regex.match(content, pattern, caseSensitive, multiLines, dotAll)
regex.matchGroups(content, pattern, caseSensitive, multiLines, dotAll)
```
Parameters:
| Parameter | Type | Purpose |
|---|---|---|
| `content` | `string` | Original text to be matched |
| `pattern` | `string` | Regular expression pattern |
| `caseSensitive` | `bool` | Whether matching is case-sensitive |
| `multiLines` | `bool` | Whether multi-line mode is enabled, so anchors match by line |
| `dotAll` | `bool` | Whether `.` matches newlines |
Return values:
- `regex.match(...) -> table`: returns all full matches, that is, the group 0 list, indexed from 1; returns an empty table if there is no match
- `regex.matchGroups(...) -> table`: returns a 2D list of capture groups for all matches, group 1..N only, excluding group 0; returns an empty table if there is no match
Return value examples:
```lua
-- regex.match(...)
{ "abc123", "xyz456" }
-- regex.matchGroups(...)
{
{ "abc", "123" },
{ "xyz", "456" }
}
```
### 13. Async Wrapper
The following async methods are globally exposed in scripts:
| Method | Example | Description |
|---|---|---|
| `task.create()` | `local awaiter = task.create()` | Create an awaiter that can be waited for by `await` |
| `async` | `async(function() end)` | Wrap a method as an async method |
| `await` | `local result = await(awaiter)` | Asynchronously wait for an awaiter and get its result |
### 14. HTTP Requests
Available HTTP methods:
```lua
http.getAsync(url, options)
http.postAsync(url, options, body)
http.putAsync(url, options, body)
http.deleteAsync(url, options, body)
```
Parameters:
| Parameter | Type | Description |
|---|---|---|
| `url` | `string` | HTTP request URL |
| `options` | `table` | HTTP request header parameters |
| `body` | `string? or table?` | HTTP request body |
Request return value:
| Parameter | Type | Description |
|---|---|---|
| `ok` | `bool` | Whether the request succeeded. `true` means success, `false` means failure |
| `statusCode` | `number?` | HTTP status code. Present only when the request succeeds, or when it fails with a `DioException` |
| `statusMessage` | `string?` | HTTP status message. Present only when the request succeeds, or when it fails with a `DioException` |
| `headers` | `table?` | Response headers. Present only when the request succeeds |
| `body` | `string?` | Response body. Present only when the request succeeds |
| `message` | `string?` | Dart-layer Error exception message. Present only when the request fails and the exception is not a `DioException` |
HTTP example:
```lua
local awaiter = http.getAsync("https://baidu.com", {})
local result = await(awaiter)
print(result.statusCode) -- 200
```
## 4. Lua Version and Sandbox Restrictions
The current rule script runtime is based on Lua `5.4.8`.
You can generally assume common basic syntax, control flow, local variables, functions, and most common standard-library features are still available, but this is not a complete, unrestricted Lua environment.
The available built-in Lua libraries and capabilities are:
- `pcall` / `xpcall`: protected calls
- `tonumber` / `tostring`: type conversion
- `type`: get the type
- `select`: select arguments
- `unpack`, compatible with `table.unpack`: unpack arrays
- `ipairs` / `pairs`: iterate arrays or tables
- `next`: get the next key-value pair
- `math`: full math library
- `table`: full table library
- `string`: full string library
- `coroutine`: full coroutine library
- `utf8`: UTF-8 support
- `os.clock()`: CPU time
- `os.date()`: date formatting
- `os.time()`: timestamp
- `os.difftime()`: time difference calculation
- `_VERSION`: Lua version string
- `print`: already redirected to `log.debug`
Do not depend on dangerous capabilities that are not explicitly documented here. Do not fake capabilities such as file read/write, system command execution, or dynamic external module loading.
## 5. Code Generation Requirements
Please strictly follow these requirements:
1. Only generate Lua scripts suitable for the ClipShare rule system.
2. Output the script body directly. Do not wrap it in `function main(params)` or `return function(params)`.
3. A table must be returned.
4. Prefer keeping the returned structure complete.
5. Only use the APIs and capabilities listed in this document.
6. Do not use libraries, functions, file read/write, system command execution, or dynamic module loading capabilities that are not listed in this document.
7. Fields with `?` in their type must be handled for nullability.
8. When the logic becomes complex, store intermediate results in local variables with clear semantic names first.
9. You may add necessary comments to help ordinary users understand the code, but do not output extra explanations.
10. If standard regex is needed, use `regex.match` or `regex.matchGroups`. Do not treat Lua Pattern as standard regex.
## 6. Example Script
Here is an example that extracts a verification code from SMS or text and adds a tag:
```lua
-- Read the original content
local content = params.content or ""
-- First check whether the content contains the "verification code" keyword (using regex.match)
local keywordMatches = regex.match(content, "verification code.*", false, false, false)
local hasCodeKeyword = #keywordMatches > 0
-- Only when the keyword is matched, extract the first group of 4 to 6 digits
local code = nil
if hasCodeKeyword then
-- Directly match 4 to 6 digits and take the first result
local codeMatches = regex.match(content, "\\d{4,6}", true, false, false)
code = codeMatches[1]
end
-- Copy the tag list to avoid directly depending on nil
local tags = params.tags or {}
-- Add the tag only when the keyword is matched and the code is extracted successfully
if hasCodeKeyword and code then
table.insert(tags, "Verification Code")
end
-- Return the processed rule result
return {
title = params.title,
content = content,
extractedContent = code,
tags = tags,
isSyncDisabled = params.isSyncDisabled or false,
isDropped = false,
isFinalRule = false,
}
```
## 7. Output Format Requirements
Unless I say otherwise, please:
- Output only Lua script code
- Do not output extra explanations
- Include necessary comments in the code
- The script must end with `return { ... }`
- Keep the returned structure complete
## 8. Gather Requirements Before Generating the Script
When the user has not provided complete requirements, do not generate a Lua script immediately. First collect the key information from the user based on the constraints above.
The user may not understand programming. Use natural language when communicating with the user. Avoid directly mentioning code field names such as `params.content`, `params.title`, or `params.type`; use the corresponding natural-language descriptions instead.
Prioritize asking for the following information, and keep it concise:
1. Trigger content examples: ask the user to provide 1 to 3 real or realistic examples of the original content; if it is related to notifications, ask for the notification title too; clarify whether the content type is text, image, SMS, or notification.
2. Target behavior: whether extraction is needed; what should be extracted; whether tags should be added or removed; whether the original content or title should be modified.
3. Rule control items: whether sync should be blocked; whether this content should be dropped; whether subsequent rules should stop.
4. Matching rule details: if regex is involved, confirm the regex pattern, whether matching is case-sensitive, whether multi-line matching is needed, and whether `.` should match newlines.
If the user information is insufficient, first output a "list of information that still needs to be provided", then wait for the user to supplement it.
If the information is already sufficient, generate the script and output only Lua script code.