DocsSlangEditor & Intellisense

Editor & Intellisense

The SlangEditor component, its syntax-highlight tokeniser, the useSlangIntellisense autocomplete hook, parameter hints, hover tooltips, and the colour settings system.

SlangEditor

SlangEditor.tsx is a self-contained editor panel. It renders a scrollable code area, a gutter with line numbers, a syntax-highlight overlay, a resizable log panel, and a top toolbar — all built with plain DOM elements and inline styles (no external code-editor library). The editor keeps its text in sync with SlangStore so that external code changes (e.g. loading a script from the library) are reflected without re-mounting.

Props

PropTypeDescription
theme'dark' | 'light'Controls the colour palette for the editor, log panel, toolbar, and syntax highlighting.

State Variables

codestring

Current script text, kept in sync with SlangStore via onSlangCodeChange.

logsLogEntry[]

Accumulated log entries from slangLogger. New entries are appended via subscribe().

logHeightnumber

Height in px of the resizable log panel (min 40, max 600).

showSavePopupboolean

Whether the "Save to library" name-input popup is visible.

savePopupNamestring

User-entered script name for the save-to-library popup.

savePopupErrorstring | null

Validation or API error shown inside the save popup.

savePopupLoadingboolean

Disables the save button while the API call is in-flight.

currentSlang{ id, name } | null

Metadata of the currently loaded library script (from SlangStore).

saveCurrentLoadingboolean

True while an overwrite-save API call is in-flight.

savePopupPos{ top, left } | null

Absolute pixel position for the save popup (calculated from the Save button rect).

Layout Structure

SlangEditorHeader

Top toolbar: Compile, Decompile, Open, Save buttons. Renders as a sticky row above the editor area.

Line-number gutter

A fixed-width column rendered as a <div> containing per-line number spans. Scroll is synced with the textarea via a negative margin-top offset.

Highlight overlay <pre>

Positioned absolutely on top of the textarea. Receives the same scroll offset so highlighted text lines up pixel-perfect with the cursor.

Editing <textarea>

The actual input element. Transparent background and matching font metrics ensure the overlay is visible through it.

Drag divider

A 4px drag handle between the editor and log panel. Mouse-down/move/up handlers update logHeight with clamping.

Log panel

A scrolling list of LogEntry items colour-coded by type (info = muted, success = green, error = red). Auto-scrolls to the latest entry.

Save popup (portal)

Rendered via createPortal() into document.body. Positioned with an absolute offset computed from the Save button's bounding rect.

Key Callbacks

CallbackDescription
handleCompileGuards against empty editor, then calls compileSlang(code) from GraphCommands.
handleDecompileCalls compileGraph() (which calls decompile() internally) and sets the returned source text into the editor.
handleClearLogsEmpties the local logs state array and calls slangLogger.clear().
handleSaveOpens the save-to-library popup, positioning it below the Save button via getBoundingClientRect().
handleSaveConfirmValidates the name field, calls apiSaveSlang(), then calls inventoryPrependSlang() to insert the new entry into the library panel without a full reload.
handleSaveCurrentOverwrites the currently loaded script (via API) and calls inventoryReplaceSlang() to update the library panel entry in-place.
handleFileSelectReads a .slang / .txt / .js / .ts file via FileReader and injects the text into the editor.
syncScrollCopies scrollTop and scrollLeft from the textarea to the highlight <pre>, and updates the gutter inner offset.

Syntax Highlighting

The highlightLine(line) callback converts each source line into an array of React <span> elements with inline colour styles from the active colour palette. Three line patterns are handled:

Comment line

Entire line → comment colour

Standalone call

indent → plainnamespace → punctuationdot → punctuationfuncName → configCommand (if action) or commandargs → tokeniseArgs()parentheses → punctuation

Assignment

indent → plainvarName → variable colour= → punctuationnamespace+dot → punctuationfuncName → command or configCommand colourargs → tokeniseArgs()parentheses → punctuation

tokeniseArgs()

The inner helper splits the raw args string by comma, then for each token applies:

Comma ,

punctuation colour

Quoted string "…" or '…'

string colour

Numeric literal -?d+(.d+)?

number colour

Any other token

variable colour (treated as a node reference)

SlangEditorHeader

A fully controlled, stateless toolbar component. All state lives in the parent SlangEditor.

PropTypeDescription
theme'dark' | 'light'Drives button and border colour tokens.
currentSlang{ id, name } | nullWhen set, the overwrite-save button is enabled and shows the script name in its tooltip.
saveCurrentLoadingbooleanDisables the overwrite-save button while the API call is pending.
codestringCurrent editor text (passed for potential future use; not currently displayed in the header).
saveBtnRefRefObject<HTMLButtonElement>Ref attached to the Save-to-library icon button so the parent can read its position for popup placement.
fileInputRefRefObject<HTMLInputElement>Ref for the hidden file input so the parent can trigger it programmatically via onOpen.
onCompile() => voidCalled when the ▶ Compile button is clicked.
onDecompile() => voidCalled when the ◀ Decompile button is clicked.
onOpen() => voidTriggers fileInputRef.current.click() to open the file picker.
onSave() => voidOpens the save-to-library popup.
onSaveCurrent() => voidOverwrites the currently loaded script via API.
onFileSelect(e) => voidHandles the file input change event.

Button layout (left → right)

▶ Compile◀ Decompile(flex spacer)📂 Open💾 Overwrite save (disabled if no currentSlang)💾 Save to library

useSlangIntellisense

useSlangIntellisense(editorRef, setCode) is a React hook that attaches keyboard and input event listeners to the textarea ref and computes suggestions in real time. It returns an IntellisenseState object that the editor passes to IntellisensePopup for rendering.

IntellisenseState

interface IntellisenseState {
  visible:          boolean;            // Is the popup currently visible?
  items:            SuggestionItem[];   // Filtered suggestions to display
  selectedIndex:    number;            // Keyboard-highlighted item index
  position:         { top: number; left: number }; // px position relative to editor
  prefix:           string;            // Partial text typed so far (for replacement)
  mode:             'command' | 'variable' | 'param' | null;
  activeCommand:    string | null;     // Command name when completing params
  activeParamIndex: number;            // 0-based param position inside ()
  activeTypedArgs:  string[];          // Already-typed args (for paramGroups resolution)
}

Suggestion Modes

Namespace suggestions

Trigger: Cursor is on an unquoted alphabetical token before a dot — e.g. typing "ta"

Items: All namespace prefixes (sc, ta, dm, rm, ex, ch, cg) filtered by the partial text. Insert text appends "." so the next suggestion immediately refines by command.

Command suggestions

Trigger: Cursor is typing the function name part (after a dot, or at start of RHS)

Items: All registered commands filtered by prefix, restricted to the declared namespace when one is present. Config/action commands (def.action) get the "config" kind badge; others get "command".

Variable suggestions

Trigger: Cursor is inside parentheses at an input-reference position (0 … inputs-1)

Items: All variable names declared on prior lines in the current script, filtered by the partial text.

Parameter suggestions

Trigger: Cursor is inside parentheses at a parameter position (≥ inputs)

Items: For known enum-like params (symbol, timespan, operator, tpType, stopType, positionType, channel), a curated list of valid values. For GETVALUE channel, resolves the input variable's outputChannels dynamically. Falls back to a generic <paramName> placeholder hint.

Keyboard Navigation

ArrowDown

Moves selectedIndex down (wraps). Prevents default textarea cursor movement.

ArrowUp

Moves selectedIndex up (wraps). Prevents default.

Tab / Enter

Accepts the highlighted suggestion: replaces the current prefix in the textarea with the item's insertText. Closes the popup.

Escape

Closes the popup without accepting any suggestion.

Alpha key (a-z, A-Z)

Re-triggers suggestion computation when triggerOnAlpha is enabled.

IntellisensePopup Component

A pure presentation component that renders the suggestion list as a fixed-position overlay. Each item shows a kind badge, the label, and the detail string (function signature or param type). Clicking an item calls the onSelect callback.

SuggestionItem kind colours

namespacecommandconfigvariableparamsnippet

useCommandHover & CommandHoverTooltip

Hovering the mouse over a command name in the editor shows a rich tooltip with the full function signature (inputs → parameters → outputs). The tooltip is positioned via clientX / clientY mouse coordinates and auto-flips below or above the cursor to stay inside the viewport.

useCommandHover(editorRef)

Attaches a mousemove listener to the textarea. On each move, it calculates the approximate character position under the cursor (using font metrics), extracts the word at that position, and looks it up in the command registry via getCommandDef(). Returns a state object with visible, commandName, def, and position.

CommandHoverTooltip

Renders the tooltip card when hover.visible is true. Shows: command name, input channels, parameters with types, and output channels. Rendered via createPortal() into document.body at a fixed z-index.

SlangConfig — Colour Settings

SlangConfig.ts defines the colour palette and intellisense knobs for the editor. Settings are persisted to localStorage under the key traderoid_slang_editor_settings and broadcast via a CustomEvent so multiple components stay in sync.

SlangColors

KeyDefault (dark)Default (light)Applied to
command#c792ea (purple)#7c3aed (purple)Normal command / function names (e.g. SMA, RSI)
configCommand#ffcb6b (gold)#b45309 (amber)Action commands (SetWindowSize, AddToChart, …)
variable#82aaff (blue)#2563eb (blue)Variable names (left-hand side of =)
string#c3e88d (green)#16a34a (green)Quoted string literals
number#f78c6c (orange)#ea580c (orange)Numeric literals
comment#546e7a (grey)#9ca3af (grey)Comment lines (// or #)
punctuation#89ddff (cyan)#0891b2 (teal)= ( ) , and namespace dots
plain#d1d4dc (light grey)#333333 (dark grey)Any other token

SlangIntellisenseSettings

SettingDefaultDescription
enabledtrueMaster toggle for all intellisense features.
triggerOnAlphatrueRe-trigger suggestions whenever an alphabetical character is typed.
maxSuggestions10Maximum items shown in the popup at once.
showParameterHintstrueShow inline parameter type hints while typing inside parentheses.
showCommandDescriptionstrueShow rich descriptions (from node definitions) for commands.
showVariableSuggestionstrueInclude previously declared variable names as input suggestions.

Config API

getSlangEditorSettings()

Returns the current settings object.

setSlangEditorSettings(settings)

Saves to localStorage and dispatches a CustomEvent so subscribers update immediately.

subscribeToSlangEditorSettings(listener)

Adds a listener for the CustomEvent. Returns an unsubscribe function.

getSlangColors(theme)

Shorthand — returns the dark or light SlangColors from the current settings.