The contract
An action defines transform(text). Whatever it returns is turned into text and inserted where you are writing.
def transform(text):
return text.upper()Return None to insert nothing. For a quick experiment, assign a top level result variable instead of defining a function.
Where the text comes from
| Input | What the action gets |
|---|---|
| Nothing | Generates text from scratch. transform(""). |
| Current word | Passes the word you're typing into transform(text). |
| Selection | Passes the text you have selected, or nothing when there is no selection. |
| Current line | Passes the line the cursor is on. |
| Current sentence | Passes the sentence the cursor is in. |
| Text before cursor | Passes everything before the cursor in. |
| Text after cursor | Passes everything after the cursor in. |
| Whole field | Passes the whole field in, on both sides of the cursor. |
| Clipboard | Passes the clipboard text in. Needs Full Access. |
Replace input decides whether the output takes the place of what went in. It applies to every source that reads the field. Nothing and Clipboard have nothing in the document to replace, so their output is always inserted.
def transform(text):
words = len(text.split())
return f"{words} words"Asking the keyboard
An action can use the same commands a panel does, instead of returning one string. That is how an action makes more than one edit, or leaves the cursor somewhere particular.
def transform(text):
replace(len(text), "(" + text + ")")
move_cursor(-1)toast() and close() belong to panels: an action has no surface of its own to show a message on. Both still appear in the run console while you are writing one.
The language
Scripts run on Clink's own interpreter rather than CPython. It reads a useful subset of Python: comprehensions, lambdas, tuples, sets, f-string formats, try and except. The rest it refuses with a message that names the line.
Types
intfloatstrboolNonelisttupledictset
Keywords
ifelifelsewhileforindefreturnbreakcontinuepassTrueFalseNoneandornotlambdatryexceptfinallyraiseimportfromasisdelglobal
Builtins
lenstrreprprintintfloatboolabsroundminmaxsumrangesortedreversedlistdictsettupleenumeratezipordchranyalltypemapfilterdivmodpowhexbinoctformatisinstancecallable
String methods
upperlowercasefoldtitlecapitalizeswapcasestriplstriprstripreplacesplitrsplitsplitlinesjoinstartswithendswithfindrfindindexrindexcountpartitionrpartitionzfillljustrjustcenterisdigitisnumericisalphaisalnumisspaceisupperisloweristitleremoveprefixremovesuffixformat
List methods
appendextendpopinsertremoveindexcountsortreverseclearcopy
Dictionary methods
keysvaluesitemsgetpoppopitemsetdefaultupdateclearcopy
Set methods
adddiscardremovepopclearcopyupdateunionintersectiondifferencesymmetric_differenceissubsetissupersetisdisjoint
Tuple methods
countindex
Regex match methods
groupgroupsgroupdictstartendspan
Exceptions
ExceptionValueErrorTypeErrorKeyErrorIndexErrorNameErrorZeroDivisionErrorAttributeErrorRuntimeErrorStopIteration
Refused
classwithnonlocalassertyieldasyncawaitmatch
Namespaces
These namespaces can be imported, and nothing else. Each one only computes: there is no filesystem, no network and no process for a script to reach.
import json
dumpsloads
import math
acosasinatanatan2ceilcombcopysigncosdegreeseexpfabsfactorialfloorfmodgcdhypotinfisfiniteisinfisnanlcmloglog10log2nanpipowprodradianssinsqrttantautrunc
import random
choicechoicesrandintrandomrandrangesampleseedshuffleuniform
import re
DOTALLIIGNORECASEMMULTILINESescapefindallfinditerfullmatchmatchsearchsplitsubsubn
import sys
version
import time
formatmonotonicpartstime
import re
def transform(text):
return re.sub(r"\s+", " ", text).strip()The regular-expression engine is Clink's own, and it spends the same step budget as the rest of your script, so a pattern that would otherwise take for ever ends with an error instead of a keyboard that stops answering. Backreferences and lookaround are not supported.
Why not CPython
A keyboard extension has a hard memory ceiling, and iOS ends it without warning when it goes over. A full Python runtime would not fit beside the keyboard, so Clink ships a small interpreter written for the job: no imports, no files, no network, and a step budget that ends a runaway script rather than the keyboard.
print goes to the console in the editor, never into what you are writing.