# The lisp interpreter The interpreter is a lisp-like language used to build the filter expressions. ## Builtins **atom**: check if a receive value is a atom. `(atom 1)` **eq**: check if two values are equal. `(eq (quote a) (quote a))` **car**: get the first item of the cons. **cdr**: get the remainder of the list. **cons**: create a new cons. `(cons 1 2)` **begin**: evaluate a series of statements, returning the result of the last one. `(begin t nil)` **+-\*/%**: arithmetic operations for integers. `(+ 1 2)` **=**, **!=**, **<**, **<=**, **>**, **>=**: compare two integers. `(> 1 2)` **not**: negate the given value. `nil -> t`, everything else will be `nil`. `(not (quote a))` **string=**, **string!=**, **string<**, **string<=**, **string>**, **string>=**: compare two strings. `(> "1" "2")` **haskeys**: takes any object and a variadic number of arguments (strings) and returns a list with either `t` or `nil` describing if a corresponding property/field/method with that name exists on the object. `(haskeys mystring "Length")` **getitems**: takes any object and a variadic number of arguments (strings) and returns the values of the fields/properties. `(getitems mystring "Length" "Chars")` **invoke**: takes 3 arguments and invokes the method defined on the object. The first argument is the object on which to invoke the method, the second one is the name of the method and the third one is a list of arguments to pass to the method. `(invoke mystring "Lower" nil)` **invoke-generic**: the same as **invoke**, but takes a fourth argument, a list of string describing the types for the generic method. `(invoke-generic mybaseitem "FindParent" nil (list "MediaBrowser.Controller.Entities.Audio.MusicArtist, MediaBrowser.Controller"))` **random**: gives a random integer. `(random)` **shuffle**: shuffles a list. `(shuffle (list 1 2 3 4))` **quote**: quotes a value. `(quote a)` **eval**: evaluates a expression. `(eval (quote a))` **cond**: checks conditions and evaluates the corresponding expression. ``` (cond (> 1 2) t (t) f) ``` **if**: a conditional. `(if t 1 2)` **define**: defines a new symbol. `(define foo 1)`, `(define add (lambda (a b) (+ a b)))` **let**: define variables in the let context and evaluate the last expression. `(let (a 1) (b 2) (+ a b))` **let\***: the same as **let**, but allows to reference variables defined earlier in the let statement. `(let* (a 1) (b (+ 2 a)) (+ a b))` **apply**: call a function with the specified arguments. `(apply + (list 1 2))` **and**: evaluate the given expressions in order, if any one of them evaluates to `nil` return early with that value, otherwise return the last value. `(and 1 2 nil 3)` **or**: return `nil` if all arguments evaluate to `nil` otherwise the first non-nil value. ## Derived builtins **null**: the same as **not**. Can be useful to indicate semantics of a program. **list**: create a list from the given arguments. `(list 1 2 3)` **find**: find if an item is in the given list and return it, otherwise return `nil`. `(find 4 (list 1 2 3 4 5 6 7))` **map**: apply a function to every item in the list. `(map (lambda (x) (* 2 x)) (list 1 2 3))` **fold**: also known as reduce. Apply the function to a sequence of values, reducing the sequence to a single item. It takes a initial value which is returned for empty lists. `(fold (lambda (a b) (+ a b)) 0 (list 1 2 3 4))` **any**: equivalent to `(apply or (map function list))`. `(any (lambda (a) (% a 2)) (list 2 4 6 7 8))` **all**: equivalent to `(apply and (map function list))`. `(all (lambda (a) (% a 2)) (list 2 4 6 7 8))` **append**: append an item to the given list. `(append (list 1 2 3) 4)` **qsort**: quicksort, takes a comparison function and the list. `(qsort (lambda (a b) (> a b)) (list 1 2 6 4 9 1 19 0))` **rand**: get a random integer. Takes either zero, one or two arguments. If zero arguments are given it gives a random integer from all possibly representable integers. If one argument is given it gives a integer between `0` (inclusive) and `n` (exclusive). If two arguments are given it gives a integer between `a` (inclusive) and `b` (exclusive). **shuf**: same as **shuffle**. ## Pre-defined convenience functions - **lower**: lowercases a string (`(eq (lower "SomeString") "somestring")`) - **is-genre**: check if the item is of this genre, partial matches allowed, the example filter would match the genre "Nu-Metal" (`(is-genre "metal" (genre-list))`) - **is-genre-exact**: the same as `is-genre`, but does not match paritally - **is-favorite**: matches a favorite item (`(is-favorite)`) - **is-type**: matches the type of item look at [BaseItemKind.cs](https://github.com/jellyfin/jellyfin/blob/master/Jellyfin.Data/Enums/BaseItemKind.cs) for a list of items. The plugin has enabled support for `Audio, MusicAlbum, Playlist` (`(is-type "Audio")`) - **logd**, **logi**, **logw**, **loge**: write to the logger with the respective levels (`debug`, `information`, `warning`, `error`). Takes the same arguments as `Logger.LogInformation(...)`. And many more.