MrC-temp: Difference between revisions

From wiki.jriver.com
Jump to navigation Jump to search
(more live updates)
(expression page done)
 
(2 intermediate revisions by the same user not shown)
Line 1: Line 1:
'''This is MrC's scratch space for work-in-progress Wiki pages.'''
'''This is MrC's scratch space for work-in-progress Wiki pages.'''


: <span style="color: red">'''Note:'''</span> The Expression language function table is now at its permanent home: [[ Media_Center_expression_language#Functions | Expression language functions ]].
: <span style="color: red">'''Note:'''</span> The Expression language page is complete and is now at its permanent home: [[ Media_Center_expression_language#Functions | Expression language functions]]


: Note: The Smartlist and Search - Rules and Modifiers page is now at its permanent home: [[Smartlist_and_Search_-_Rules_and_Modifiers|Smartlist and Search - Rules and Modifiers]]
: Note: The Smartlist and Search - Rules and Modifiers page is now at its permanent home: [[Smartlist_and_Search_-_Rules_and_Modifiers|Smartlist and Search - Rules and Modifiers]]
Line 14: Line 14:


----
----

==Overview==

Media Center provides a simple programming language that enhances and enriches its overall user interface and usability.
This language, commonly called the expression language is simple to learn, simple to use, and can greatly enhance your experience using Media Center.

Expressions are ubiquitous throughout Media Center, used in areas such as:
:* The categories in a view
:* File list expression columns
:* Theater View
:* Customized view headers, grouping and sort criteria
:* The library field manager (fields with data type Calculated data)
:* File and folder location definitions
:* Auto-import rules
:* Custom DLNA titles
:* The player's display
:* Captions and thumbnail text
:* The link manager (expressions help format link URLs)
:* Rename, Move, & Copy tool
:* Tag assignment
:* Complex search queries

==The Expression Language==

An expression is a mixture of ordinary text, pre-defined functions, and a few reserved characters and
constructs that have special meaning.
An expression is evaluated by Media Center's expression engine and textual output is produced.
This output is then used by Media Center to customize the user interface and affect its method of operation.

===The Anatomy of an Expression===

As mentioned above, an expression is a mixture of text and function calls (and some reserved stuff described shortly).
The simplest expression would be some basic, literal text, such as <span style="font-family: Consolas, monospace;">A good movie</span>.
The expression engine evaluates this expression, finds nothing special, and then outputs the result: <span style="font-family: Consolas, monospace;">A good movie</span>. Simple.

But simple text only has so much utility.
The ability to transform or generate content is much more interesting and useful.
And this is when functions are employed.
Media Center provides many functions, which when called, produce some output.
Most functions require some form of input, called arguments, and most functions generate output.
By supplying a function with various arguments, the function will return some output value which is just more text.
And this output text can be the used by other functions, and so on.
Each function has a unique name, and calling upon a function to do some work requires little more that using its name anywhere in the expression.

A function call looks like this:

<div style="margin-left: 20pt"><span style="font-family: Consolas, monospace;"><i>functionname</i><b>(</b><i>argument 1</i>, <i>argument 2</i>, ...<b>)</b></span></div>

The syntax of the function call is the function's case-insensitive name, immediately followed by an opening parenthesis character, one or more comma-separated arguments, and a closing parenthesis character.
Whitespace after the commas is optional, but helps readability and formatting.
And each argument itself is also just an expression. And some arguments are optional.
Here is an example using the FixCase() function to change its input to Title Case:

<div style="margin-left: 20pt"><span style="font-family: Consolas, monospace;">fixcase(A good movie)</span></div>

which outputs <span style="font-family: Consolas, monospace;">A Good Movie</span>.

A slightly more complex expression example consists of both text and a nested function call:

:<span style="font-family: Consolas, monospace;">Wow! fixcase(replace(A good movie, good, great))</span>

Inner functions are called before outer functions, so the output of the [[#Replace|Replace()]] function

<div style="margin-left: 20pt"><span style="font-family: Consolas, monospace;">replace(A good movie, good, great)</span></div>

is then supplied as the input to the [[#FixCase|FixCase()]] function. [[#Replace|Replace()]] does its work substituting <span style="font-family: Consolas, monospace;">good</span> with <span style="font-family: Consolas, monospace;">great</span>, and returns <span style="font-family: Consolas, monospace;">A great movie</span>.
This output is then supplied as the argument to [[#FixCase|FixCase()]] which sees only the text <span style="font-family: Consolas, monospace;">A great movie</span> (it knows nothing about how it was produced):

<div style="margin-left: 20pt"><span style="font-family: Consolas, monospace;">fixcase(A great movie)</span></div>

which in turn outputs <span style="font-family: Consolas, monospace;">A Great Movie</span>.
Now that the functions have produced their output, the final output, including the literal <span style="font-family: Consolas, monospace;">Wow! </span> leading text is

<div style="margin-left: 20pt"><span style="font-family: Consolas, monospace;">Wow! A Great Movie</span></div>

===Fields===
The expression examples thus far have been limited to static literal text.
Expressions have much more utility when they use data from other sources, such as a file's metadata.
Media Center maintains this metadata in its defined fields.
This data is accessed using the function called Field(), and its first argument is the case-insensitive name of the desired field.
This function when called returns the file's value for that field.
For example, the function call Field(album) will return the file's value for the album field.
If the album field contained the value <span style="font-family: Consolas, monospace;">After Hours</span>, the expression:

<div style="margin-left: 20pt"><span style="font-family: Consolas, monospace;">fixcase(field(album), 3)</span></div>

would produce <span style="font-family: Consolas, monospace;">AFTER HOURS</span>.
First <span style="font-family: Consolas, monospace;">field(album)</span> is evaluated, returning <span style="font-family: Consolas, monospace;">After Hours</span>.
The FixCase() function is supplied with this output as its first argument, and its second argument is <span style="font-family: Consolas, monospace;">3</span>, which happens to specify that it should perform uppercasing.

Because fields are so frequently used in expressions, an abbreviated form exists for accessing their values. This makes it easier to both read and write expressions.
Nonetheless, both forms are equivalent.
The abbreviated form is simple: immediately surround the field's name with opening and closing square brackets, such as <span style="font-family: Consolas, monospace;">[album]</span>.
The previous example is now written more simply as:

<div style="margin-left: 20pt"><span style="font-family: Consolas, monospace;">fixcase([album], 3)</span></div>

====Field Values====
For the sake of simplicity and clarity, the section above glossed over an important detail regarding how
Media Center outputs field values.
Recall that [[#Field|Field()]] is the function used to return the value of a specified field.
But [[#Field|Field()]] also has a second argument that indicates the format of the value that it returns.
Because field values are used in a variety of situations, the [[#Field|Field()]] function can produce output suitably formatted for the requirements.
There are two forms of output: one is a nice, friendly human-readable format suitable for use in views or other display locations; the other is a raw format which returns the representation stored internally by Media Center which is useful when uninterpreted values are necessary.

By default, Media Center <i>always</i> outputs the friendly format, so expressions sometimes need to take this into account and chose the format accordingly.

Not used earlier because it is optional, the second argument to the [[#Field|Field()]] function selects the mode of output:
the value <span style="font-family: Consolas, monospace;">0</span> selects the raw mode, and the default value of <span style="font-family: Consolas, monospace;">1</span> selects the friendly mode.
Here are two examples using the date field, the first one outputs the date value in raw format, the second in the friendly format:

<div style="margin-left: 20pt"><span style="font-family: Consolas, monospace;">field(date, 0)</span></div>
<div style="margin-left: 20pt"><span style="font-family: Consolas, monospace;">field(date, 1)</span></div>

===Expression Language Syntax===
Now that the basics have been covered, the more rigorous rules of the expression language syntax can be described.

:* An expression is any sequence of literal text and any number of function calls.
:* Expressions are read and evaluated left to right. Literal text is output unmodified, function calls are evaluated and their return values output.
:* Nested functions calls are evaluated from the innermost function to outermost function, and again, left to right when one function follows another.
:* Field abbreviations are expanded into the equivalent [[#Field|Field()]] function call
:* A functions is evaluated and its returned value contextually replaces the function call in the expression
:* Within a function's argument list, whitespace is ignored before and after commas, after an opening parenthesis, and before a closing parenthesis.
:* The forward-slash escape character <span style="font-family: Consolas, monospace;">/</span> disables the special meaning of the character that follows it.
:* The escape sequence <span style="font-family: Consolas, monospace;">/#</span> followed by <span style="font-family: Consolas, monospace;">#/</span> escapes everything inside.
:* To use a literal parenthesis, comma, or whitespace inside of function argument lists, escape them. Whitespace within an argument's value is literal and does not need to be escaped when it is surrounded by other non-whitespace text.
:* An expression may be split into multiple lines, but when it does not satisfy the conditions above regarding whitespace around function parenthesis and commas, use a forward-slash escape as the last character before the newline. Extraneous newlines in the expression editor will produce a trailing ellipsis (...) in the output.

===Expression Editors===
There are a couple of variations of dialog or edit field used to enter expressions.
Some allow multi-line expressions, while others are single line, but can be expanded to multi-line editors.
Unfortunately, some single-line editors flatten multi-line expressions into a single line, replacing the newlines with spaces.
This author is hopeful this will be rectified someday.

===How Expressions Are Evaluated===
Expressions are evaluated in the context where they are used.
For example, an expression column in a file list is evaluated relative to those files in the file list.
And the general flow is that for each file in the list, the expression is evaluated and produces output.
The expression only has access to the fields available for the file currently being evaluated.
This is important to remember, so it bears repeating.
One file after another, an expression is evaluated against that single file, its output is produced and stored away for use later,
and then the result of that evaluation is entirely forgotten before the next file is evaluated.
This means, the expression evaluator cannot use the results from one file's evaluated expression with the results of another
file's evaluation.

===Expressions and Locales===
Media Center will respect the Windows locale setting for output values produced by certain functions,
and within the values of certain fields.
This is important to consider when writing expressions that consume such values.
Under most circumstances, such values cause no harm.
However special care must be taken with functions that require the use of period as the decimal point.
One such function is [[#Math|Math()]], which always uses period as the decimal point.
If your locale uses some other character such as comma, these characters will have to be converted into periods before the
critical function is called.
Handling this problem is not difficult. Before passing to [[#Math|Math()]] any floating point number,
use [[#Replace|Replace()]] first when necessary to convert the locale's decimal character into a period.
Fields that cause problems are any fields that produce floating-point values,
such as any Date type field in raw format (e.g. <span style="font-family: Consolas, monospace;">[date,0]</span>, <span style="font-family: Consolas, monospace;">[last played,0]</span>, <span style="font-family: Consolas, monospace;">[date modified,0]</span>, and <span style="font-family: Consolas, monospace;">[date imported,0]</span>),
or any textual field that contains floating-point values that will be used for various calculations
(e.g. any of the Dynamic Range variants).
Certain functions such as [[#Now|Now()]] and [[#ConvertTime|ConvertTime()]] also return localized floating-point values.
Consider also that the expression parser uses comma as the argument separator.
Any literal numeric values specified as a function argument must have any embedded commas escaped.

====A Complex Expression Example====
Here is a more complex expression example that illustrates the various rules discussed above regarding expressions:

<span style="font-family: Consolas, monospace;">
<div style="margin-left: 20pt">if( IsEmpty( [Disc #] ),</div>
<div style="margin-left: 40pt">Disc number is empty,</div>
<div style="margin-left: 40pt">Delimit(</div>
<div style="margin-left: 60pt">field(disc #) , </div>
<div style="margin-left: 60pt">/) ,</div>
<div style="margin-left: 60pt">DISC /(</div>
<div style="margin-left: 40pt">)</div>
<div style="margin-left: 20pt">)</div>
</span>

The expression demonstrates that
:* whitespace before and after commas or opening and closing parenthesis is ignored
:* expressions can be safely split into multiple lines using the whitespace rules just mentioned
:* function and field names are case insensitive
:* forward slash is used and required to escape parenthesis (see inside the [[#Delimit|Delimit()]] function)
:* whitespace does not require escapement when surrounded by other characters (see after the <span style="font-family: Consolas, monospace;">C</span> in <span style="font-family: Consolas, monospace;">DISC</span>)
:* literal text is output unmodified (<span style="font-family: Consolas, monospace;">Disc number is empty</span>)
:* functions can be nested (Both [[#IsEmpty|IsEmpty()]] and [[#Delimit|Delimit()]] are nested within the [[#If|If()]] function, and the [[#Field|Field()]] function is nested within [[#Delimit|Delimit()]]

When the expression is run, files that have no disc number will produce <span style="font-family: Consolas, monospace;">Disc number is empty</span>,
and files that have, say, a disc number value of <span style="font-family: Consolas, monospace;">3</span> will produce <span style="font-family: Consolas, monospace;">DISC (3)</span>.

===Field Assignment===

<div>
The output of an expression can be used to assign a value to a tag.
This is accomplished by preceding the expression with an <span style="font-family: Consolas, monospace;">=</span> character.
The <span style="font-family: Consolas, monospace;">=</span> character causes the tagging engine to invoke the expression evaluator first,
and then to use its output as the value to assign to the field.
[[File:Field_Assignment_with_Expression.png|right]]
Without the prepended <span style="font-family: Consolas, monospace;">=</span> character, the literal expression text itself and not its evaluated value would be stored in the tag.
The expression can refer to the field's own value to modify itself, and this offers a convenient way to perform complex transformations on field values.
For example, the assignment expression

<div style="margin-left: 20pt"><span style="font-family: Consolas, monospace;">=removeleft([name], 4)</span></div>

entered into an edit cell for the <span style="font-family: Consolas, monospace;">name</span> field would remove
four characters from the left of the <span style="font-family: Consolas, monospace;">name</span> field's current value.
An assignment expression can be entered into the Tag Action Window, or by using inline editing in the file list or a pane entry.
The image on the right shows inplace field assignment.

Note: Undo is supported, reverting each tag to its value prior to the assignment.
Redo is also supported, reapplying the most recent Undo.
</div>

===Expressions and Search===
The expression language is fully available to the search query engine (Search, Set rules for file display, etc.).
This allows creation of more complex search queries than would otherwise be possible.
An expression-based search query is any valid expression that produces a zero or non-zero numeric output.
The syntax of the query is:

<div style="margin-left: 20pt"><span style="font-family: Consolas, monospace;"><b>[=</b><i>expression</i><b>]=</b><i>numval</i></span></div>

where expression is any valid expression, and numval is the expected numeric output produced by the expression.
The expression is evaluated against the current list of available files and the expression output numerically compared against numval.
All files for which the comparison is true are returned as part of the file list produced by the query and all files that fail the comparison are winnowed from the file list.

The following example illustrates an expression-based search query:

<div style="margin-left: 20pt"><span style="font-family: Consolas, monospace;">[=ismissing([filename (path)]\Folder.jpg)]=1</span></div>

The [[#IsMissing|IsMissing()]] function is run using the file name argument <span style="font-family: Consolas, monospace;">[filename (path)]</span> appended by <span style="font-family: Consolas, monospace;">\Folder.jpg</span>,
and returns a Boolean value <span style="font-family: Consolas, monospace;">1</span> for files that are missing, and this <span style="font-family: Consolas, monospace;">1</span> is compared against the value <i>numval</i>.
All these files where there was a successful comparision are returned in the file list,
and all those for which the expression produced <span style="font-family: Consolas, monospace;">0</span> are filtered from the file list.
By inverting the comparison and using a <span style="font-family: Consolas, monospace;">0</span> numval, the set of files remaining in the file list would be those that did not match.

===Data Types===
It was mentioned already that the Media Center expression language is primarily a textual language - it consumes and produces text.
Nonetheless, certain areas of Media Center are influenced by the type of data used or presented,
and sometimes it is useful or necessary to coerce expression output into one data type or another.
Each Media Center field is defined to be of a certain data type,
listed in the [[File_Properties_%28tags%29#Field_Specifications|Field Data Types]] table.
These types influence how values are output, sorted, and interpreted on input.
And expressions always output data of type String.
By coercing the data type of an expression, output formatting and sorting can be controlled in various ways.

Data types are forced by appending to an expression the string:

<div style="margin-left: 20pt"><span style="font-family: Consolas, monospace;">&datatype=[<i>type</i>]</span></div>

where <i><span style="font-family: Consolas, monospace;">type</span></i> is one of the following values:

<div style="margin-left: 20pt;"><table style="border-spacing:0px; border-collapse:collapse">
<tr><td style="text-align:left; padding-right:20pt"><b>list</b></td><td>A list of strings, separated by semicolons</td></tr>
<tr><td style="text-align:left; padding-right:20pt"><b>string</b></td><td>Sorts as strings (with smart number handling)</td></tr>
<tr><td style="text-align:left; padding-right:20pt"><b>number</b></td><td>Sorts values as numbers (decimal or integer)</td></tr>
<tr><td style="text-align:left; padding-right:20pt"><b>integer</b></td><td>Sorts values as integers</td></tr>
<tr><td style="text-align:left; padding-right:20pt"><b>path</b></td><td>Sorts using a smart filename compare style</td></tr>
<tr><td style="text-align:left; padding-right:20pt"><b>month</b></td><td>Sorts string month names (i.e. January, February, etc.)</td></tr>
</table></div>

====Lists and Trees====
<div>
[[File:Datatype_List.png|right]]
The list of output in view categories and pane columns can be modified by forcing the data type to a List type.
Two things happen when the data type is List:
The values within a List type are split into their individual (semicolon-separated) list items
The backslash character takes on a special meaning and becomes another form of separator that creates tree-like hierarchies,
collapsable in panes columns and creates drill-down categories in any category view type (Standard View > Categories, Theater View, DLNA, Gizmo/WebGizmo).
Forcing an expression's type to <span style="font-family: Consolas, monospace;">list</span> causes this list item separation and hierarchy generation.
Alternatively, forcing a List type to <span style="font-family: Consolas, monospace;">string</span> defeats this.
Add the cast:

<div style="margin-left: 20pt"><span style="font-family: Consolas, monospace;">&datatype=[list]</span></div>

to the end of an expression to force an expression's output to be considered as a List type.
Conversely, a List type may be forced into a String type by ading the cast:

<div style="margin-left: 20pt"><span style="font-family: Consolas, monospace;">&datatype=[string]</span></div>

to the end of an expression.
</div>

====Sort Order====
<div>
[[File:Datatype_Month.png|right]]
Normally strings are sorted ASCII-betically with some smart numeric sorting.
But this form of sort may not always be desired.

====Sorting by Month====
Generally it is more useful to see month names sorting such that January sorts before April, instead of alphabetically where April would sort before January.
Forcing an expression's type to Month forces string month values to be treated instead as their equivalent numerical month numbers.
For example, the first month January and the third month March sort before the fourth month April.
Add the cast:

<div style="margin-left: 20pt"><span style="font-family: Consolas, monospace;">&datatype=[month]</span></div>

to the end of an expression to force an expression's output to be sorted by numberic month values.

====Sorting by Path====

Path data types sort using smart filename comparisons.

XXX complete this: Path sorting always seems to be used.

Add the cast:

<div style="margin-left: 20pt"><span style="font-family: Consolas, monospace;">&datatype=[path]</span></div>

to the end of an expression to force an expression's output to be smart-sorted by path components.

</div>


... and more to come...
... and more to come...

Latest revision as of 19:18, 26 August 2013

This is MrC's scratch space for work-in-progress Wiki pages.

Note: The Expression language page is complete and is now at its permanent home: Expression language functions
Note: The Smartlist and Search - Rules and Modifiers page is now at its permanent home: Smartlist and Search - Rules and Modifiers
Note: The Regex() page is now at its permanent home: MC expression language page
Note: The File Properties page is now at its permanent home: File Properties (tags) page

Caution: Debris Ahead...


... and more to come...