LSL Style Guide
LSL Portal | Functions | Events | Types | Operators | Constants | Flow Control | Script Library | Categorized Library | Tutorials |
Every major open-source project has its own style guide: a set of conventions (sometimes arbitrary) about how to write code for that project. It is much easier to understand a large codebase when all the code in it is in a consistent style. These guidelines, referred to collectively as a Style Guide, are not as rigid as the rules required by the language compiler but nonetheless are critical to creating maintainable code. The most critical aspect of a style is that you apply it consistently to the code you write.
Effective programming in LSL requires that developers use a disciplined approach towards formatting and other conventions in their scripts.
![]() |
Important: First head fake: If you haven't noticed it by now, applying a style guide to your code does not only help others read your code. It helps you as well, because at some point in the distant future you might come back to the code you wrote before. And that's when you'll appreciate reading formatted code and not having a major headache. |
Use third party editors:
There are many third party editors with LSL syntax files available. See an example below of what your workflow would look like using an editor that has syntax highlighting and autocomplete and also applies an indent style to your code.

You can see now, that using third party editors has a few advantages over using the editor in the viewers:
- Autocompletion helps you avoid typos.
- Autocompletion sometimes not only does a linear autocompletion as in autocompleting
llS
tollSay
but sometimes works even with fuzzy search by autocompletingllslppf
tollSetLinkPrimitiveParamsFast
. - The syntax highlighting file colors the code exactly like the code you see in the official Linden Lab viewer making you not having to learn or adapt to a different coloring scheme.
- Autocompletion might also preformat code with indent styles when autocompleting states, events, conditional clauses etc.
Indent styles:
Most people, when they start programming on their own, will have programs that are UGLY to look at - to put it nicely, sometimes mistakenly thinking that such scripts occupy less space when compiled. Such scripts typically look like the following:
unstyled source code |
---|
<lsl>default {state_entry(){llSay(PUBLIC_CHANNEL,"Hello World.");}}</lsl> |
However, that code is difficult to read (or at least to follow) - even more so when one is writing a couple hundred lines program. There are several indent styles with the two most common styles being:
K&R style (used in Javascript based languages) | BSD style (used in C based languages) |
---|---|
<lsl>
default { state_entry() { llSay(PUBLIC_CHANNEL, "Hello World."); } } </lsl> |
<lsl> default { state_entry() { llSay(PUBLIC_CHANNEL, "Hello World."); } } </lsl> |
The K&R style conserves space - IN THE SOURCE CODE ONLY, however the BSD style is easier to read and easier to visually bracket-match. Once a scripter is in the practice of using a particular style, reading code in that style will become easier.
Consistent indenting makes reading both styles easier that's why it really comes down to whatever works for you. In both methods, indenting is the key indicating factor of levels of scope.
Naming conventions:
There are many naming conventions in Second Life. Only the most used ones will be listed below.
Global Variables (variables used through out the entire program) should be lowercase. For example:
<lsl> integer index = 0; string name = "Please set one"; </lsl>
Others prefer to distinguish between global and local variables by prefixing variable names with a character, defining globals in the following manner:
<lsl> integer gIndex; string gName = "Please set one"; </lsl>
Constant variables should be in ALL CAPS following the style guide used by Linden Labs. For example:
<lsl> integer DIALOG_CHANNEL = -517265; vector RED = <1.0, 0.0, 0.0>; </lsl>
Arguments used within a or one of the standard events should be named with easily readable and meaningful names. When using events, please use the standard names as listed here on the official wiki. An overview of all events can be found here. Below is an example as can be found for the listen event:
<lsl> // ...
listen(integer channel, string name, key id, string message) { key OwnerKey = llGetOwner(); if (channel == 1 && id == OwnerKey) llOwnerSay("Hello Avatar"); }
// ... </lsl>
Separating code:
Many people will start out doing many, many function calls on one line. This makes the code hard to read, and almost impossible to debug. The following is an example of one such program:
<lsl> list lst; integer numDigits = 10;
default {
touch_start(integer n) { integer i; integer index = llListFindList(lst, [llToLower(llGetSubString(llList2String(llParseString2List(llKey2Name(llDetectedKey(i)), [" "], []), 0), 0, numDigits - 1))]); if (!~llListFindList(lst, [llToLower(llGetSubString(llList2String(llParseString2List(llKey2Name(llDetectedKey(i)), [" "], []), 0), 0, numDigits - 1))])) lst += llToLower(llGetSubString(llList2String(llParseString2List(llKey2Name(llDetectedKey(i)), [" "], []), 0), 0, numDigits - 1)); llOwnerSay(llList2CSV(lst)); }
} </lsl>
Now here is the code, with the exact same features, in a simpler way. While hardly anyone could tell you what the above code did, almost everyone can tell you what the below code does.
<lsl> list listOfStrings; integer numDigits = 10;
default {
touch_start(integer n) { key owner = llGetOwner(); key id = llDetectedKey(0); string name = llDetectedName(0);// or llKey2Name(id)
list nameAsList = llParseString2List(name, [" "], []); string firstName = llList2String(nameAsList, 0); string startPart = llToLower(llGetSubString(firstName, 0, numDigits - 1)); integer index = llListFindList(listOfStrings, [startPart]);
// if index is equal to -1
if (index == ERR_GENERIC) { listOfStrings += startPart; }
// send a message to the owner, only reaches owner if online and within the same sim
llRegionSayTo(owner, PUBLIC_CHANNEL, llList2CSV(listOfStrings)); }
} </lsl>
LSL lacks an optimizing compiler. For this reason it may be necessary to balance the two style to get faster, more compact executable code. Line combination optimization should only be done after the code is working & bug free. Improper optimization can lead to wrong results. Always test optimized code thoroughly.
Script Structure
LSL scripts are comprised of expressions, functions, statements, event handlers and states. The LSL compiler mandates a certain structure to scripts:
- User Defined Variables (see LSL_Variables)
- User Defined Functions (see User-defined_functions)
- default State (see State)
- User Defined States