Index Multi-line Scripts and Multi-Scripts Scripting and User-Defined Commands Step Mode: Stepping Through Scripts Variables Scope and Lifetime: Local, Global, and Permanent Variables Introduction XYplorer Scripting, introduced with version 7.0, can truly be seen as the ultimate in file management efficiency. Roll your own custom commands, combine them to scripts, wrap them in an XYplorer Script file (XYS), or a User-Defined Command, and trigger them by just a click or a keystroke. You may share scripts with colleagues, or download them from the internet. Just drop a script file into your app folder and fresh plug-in commands are at your finger tips. Without doubt, scripting is an advanced feature that only pays off if you take the time to dive into it and explore the ways and possibilities. However, you will eventually find out that it ain't rocket science at all. More information, downloads, and a growing pool of examples is available here: Warming Up To get you started let's try something easy: (1) Select menu Scripting | Run Script... (2) Paste msg "Hello world!" into the edit box. (3) Click OK. You should see a "Hello world!" message box now. Well done, you just wrote your first XYplorer script! Okay, now for something a little bit more interesting:
Examples This little script will rename all currently selected items by appending the current date: rename b, "*-<datem yyyymmdd>" This script goes to the Desktop folder (ensuring that the listing is unfiltered), sorts the list by date modified (descending), selects the first item, and moves the focus to the list: goto "Desktop|"; sortby m, d; sel 1; focus List; Numbered Arguments Instead of counting commas you now can prefix the position of the argument to the argument itself. The separator is ":=", the first position is 0 (zero). For example, instead of this: text popupmenu("A,B,C", , , , , , ","); You can do this: text popupmenu("A,B,C", 6:=","); You can even do this (reversed or arbitrary order): text popupmenu(6:=",", 0:="A,B,C"); Or this (processing is from left to right, the last mapping wins): text popupmenu("a,b", 6:=";", 6:="|", 6:=",", 0:="A,B,C"); Concatenation Strings and variables can be concatenated by dots. Any number of blanks surrounding the concatenator are ignored. The following scripts are identical: msg "Hi there!" msg "Hi "."there!" msg "Hi " . "there!" msg "Hi " . "there!" msg "Hi"." "."there!" It's strongly recommended that you (double- or single-) quote your strings! While the script engine is currently still permissive with unquoted strings (msg Hi! works) this might not be so in the future, so you better do msg "Hi!" right away! Here's the basic laws of quoting:
There are two types of commands: commands (proper) and functions. Contrary to commands (e.g. echo), functions (e.g. quote()) return an in-place value. In the first example, the quoting is achieved by doubled double-quotes. The only command in the statement is echo. In the second example, the quoting is achieved through the function quote(): echo """Hi!"""; //"Hi!" echo quote("Hi!"); //"Hi!" Remarks on Functions
Command Prefixes Now you can add a prefix to each command to modify its behavior. Currently one prefix is implemented: e = skip the big error debugging dialog The prefix is separated from the command by | (pipe). For example, when you run this command in the drives listing: rename , '*-<datem yyyymmdd>'; //shows error dialog e|rename , '*-<datem yyyymmdd>'; //skips error dialog Quick Scripting means: Scripts, when prefixed with "::" (double-colon), can be executed directly (i.e. quickly) through any interface in XYplorer that can process locations: Address Bar, Go To, Favorites, Catalog etc. This gives you a lot of choices for usage and storage of scripts. Let's try: Paste ::msg "Hello world!" into the Address Bar and press Enter. You should see a "Hello world!" message box. Now, for mouse users, the Catalog is a very good place for scripts. Using the "::" prefix, scripts can be simply entered into the Location field of a catalog item. They are executed on a single click. For example:
But how did this work? And what is #1026? Read on... Note: From version 9.70 onwards the "::" prefix is not necessary anymore when you end your script line with a trailing ";" (appended comments after the ";" are allowed). This behavior is enabled by the INI setting ScriptSmartDetect=1. In XYplorer almost every function has a fixed number, the function ID, by which it can be referred to in a script. ID #1026 happens to refer to "Miscellaneous / Find Files / Open Find Files and Reset". Open the Customize Keyboard Shortcuts dialog (menu Tools) and find this function in category Miscellaneous. At the bottom of the dialog you'll see a button showing the function's ID. Clicking this button will copy the function's ID to the clipboard, making it easy to use it in a script. You can execute almost any function in XY in a script by referring to its function ID. E.g. #230 will pop up the submenu "New" of menu Edit. Step Mode: Stepping Through Scripts Suppose you have an older script #230, and you forgot what #230 refers to. Or you downloaded a script from the internet, and don't know exactly what it does. What now? Very simple, enter Step Mode:
A small window, the Step Dialog, will pop up and tell you what is about to happen. You can now decide whether to execute the command, or skip it, or cancel the whole script. In stepping mode you are on the safe side. It is highly recommended when writing or debugging scripts! There's also a toolbar button for toggling the stepping mode. When pressed (stepping is ON) its color changes to red to make the current state very clear. Error Messaging and Risk Classes The Step Dialog also tells you what went wrong where, and it informs you about the potential risk associated with the command to be executed. There are the following risk classes:
Class #3, #2, and #1 are marked with a yellow "warning" icon, class #0 with a blue marble (think "cool") icon. Script Context The first two lines in the Step Dialog display (1) the current script resource, and (2) the current script caption. Valuable information when writing and debugging scripts. How Functions are Stepped Functions are individually stepped. The current script line is marked green when a contained function is stepped as opposed to the main command of the line. You can even skip (button Skip) functions individually, in which case the function name is returned with the resolved arguments. For example: msg quote(chr(64));
When you "Continue without Stepping" on a function, the stepping is only suspended for all functions in the current script line / command. Variables... (Button) Click the Variables... button to display all currently assigned variables with their current values. Within the new "Variables on Stack" dialog you can double-click any listed variable to show its current value. Right-click that button for further options: Show User Functions will list all currently declared user functions. Within the new "User Functions" dialog you can double-click any listed function to show its code. Scripting and User-Defined Commands Now, for passionate keyboarders, there are User-Defined Commands (UDCs). Using the "::" prefix, scripts can be simply entered into the Location field of a UDC Go To item, which then can be assigned a keyboard shortcut to. For example:
Now press Ctrl+Alt+3. You should see a small window displaying the current textual contents of the clipboard. Of course, you don't have to abuse the UDC Go To for scripts. There's also the UDC Run Script which accepts scripts without a prefixed "::", e.g. text "<clipboard>". Run Script can also handle more advanced stuff like multi-line scripts, and multi-scripts, the rules and possibilities of which will be further explained below under "XYplorer Script Files". Multi-line Scripts and Multi-Scripts A script can have more than one line (multi-line script), and a script resource can have more than one script (multi-script). There is one important formatting rule for multi-line scripts: In a multi-line script all lines apart from the first line have to be indented by at least one space. Each non-indented line is interpreted as the first line of a separate script, and if there are more than one scripts in a loaded script resource (i.e. a multi-script) then a menu is popped where you can select the script to run. For example, this is a multi-script containing two multi-line scripts. In the first script, the script caption (which is used as the menu caption) forms the first line: "Go to C:\" Comments are an exception: Any number of non-indented comments can be prefixed to a multi-line script. Actually non-indented comments can be inserted anywhere. This script is functionally identical to the above one: // comment 1 Initialize and Terminate You can define two special-named scripts within multi-scripts, "_Initialize" and "_Terminate". They can be placed anywhere in the multi-script, and they are not shown in the popup menu. The script called "_Initialize" will be auto-processed before the menu is popped. The script called "_Terminate" will be auto-processed after the script selected from the menu has been processed (or after the menu has been canceled). Note: If a script within a multi-script is called directly (SCs Sub or Load), then "_Initialize"/"_Terminate" are NOT called. For example, this multi-script defines a permanent variable (which is also global by definition), then offers various scripts in a popup menu, then finally removes the variable from memory: "_Initialize" Here we are talking popup menus that are user-defined by a text file. Let's make one: Create a new text file in any editor. Paste the following multi-line script (see above): // some little test scripts Save the file as "test.xys" (XYplorer Script File) in XYplorer's Scripts folder. In case you don't know that path, use menu Scripting | Go to Scripts Folder to go there. Now, in XYplorer, click menu Scripting | Load Script Files... and open "test.xys". The following menu should pop up at your mouse cursor: Go to C:\ Go to System Folder Go to XYplorer Folder Now you can choose where you want to go. A script file is basically a library of scripts. It is nothing more than a simple text file, which can contain one or more scripts. You will be able to either call one of those scripts directly, or simply load the entire file. In such case, XY will create a menu based on the contained scripts in that file and pop it up, allowing you to choose which script to execute. The syntax for the scripts themselves within script files is exactly the same as for scripts anywhere else in XY since this is just another way to store and execute scripts. Syntax rules for XYplorer Script Files
To Load a Script File do one of the following:
The existence of a command load, of course, means that one script file can load another. You will get an idea of the potential of scripting by now... You can drop files onto XYS-files. The dropped files are referred to in the dropped-on script by <get drop>. This can get pretty cool in Dual Pane mode. You can have a folder with assorted script files in one pane, and your working folder in the other pane. Now you just drag-and-drop files onto the scripts for automated processing. Primitive example script in a file "drop_on_me.xys": text <get drop>; Even cooler: You can also drop on multi-scripts. In that case you get the usual popup menu of choices, and the <get drop> will be available in each of the scripts. Primitive example script in file "drop_on_me_2.xys": "Text" Notes:
Labels By using labels you can execute a script inside a file directly, avoiding the popup menu. The label is attached to the caption, separated by " : " (space-colon-space). For example: // some little test scripts, using labels If the above is saved to a file called "test.xys" in application data path then the following command will directly bring you to the System folder: load "test.xys", "system". You may as well specify a list of labels, by which you can easily control which scripts are displayed in the popup menu, and in which order. See load for the details. Wildcard catch-all label: The label "*" matches all load calls if more than one label is stated. The third command will be shown on load "test.xys", "croot;system": // some little test scripts, using labels Hiding scripts inside a script file Hidden scripts can be executed but are not shown in the script file's popup menu. To hide a script simply prefix an underscore to the caption or label (a hidden script does not need a caption anyway). For example, create a script file "date.xys" in application data path with the following contents: // this is in script file "date.xys" Now execute the script load "date.xys". The popup menu will show only two of the four contained scripts. Select either and see what happens. Now run the script load "date.xys", "date". The script with the label "date" will be executed directly. It has only one command: sub "_date";. The sub command is a special command to call a script inside the same script file. In this case the hidden script with the label "_date" is called and executed. Its command msg "<date yyyy-mm-dd>" produces the message box showing the current date. Variables in Captions The captions of scripts in multi-script resources may contain XYplorer native variables. They are resolved in the moment the menu is popped up. For example, paste this into the Try Script box: "Go to <xypath>" The 2nd script will show two different times if you wait longer than a second before you click the menu item. Also Environment Variables and Permanent Variables are supported in captions. Icons, States, and Levels You can optionally define an icon and a state for each menu item. Syntax: "Caption|Icon|State|Level : Label" Script Examples for States "Go C:|C:|1" goto "C:\"; //shown bold Icon can be any file or folder, and its small system icon (the one you see in Details View) will be used for the menu, or a PNG, JPG, GIF, BMP, or TIF file. XY variables and environment variables are supported. The path defaults to the XY icon path <xyicons>. You can as well use XYplorer's internal toolbar icons using the button key, e.g.: "Funny Script|Icons\fun.ico" echo "Ha!"; Note that the icon specification in a multi-script resource supports permanent global variables. You can as well use generic file icons in the multi-script menus by passing the generic extension as "*.ext": "Megan|*.png" echo 'hello'; You can as well pass * as placeholder to use the caption as icon pointer: "C:\|*" goto "C:\"; Levels: Multi-Scripts support nesting. The level is simply stated by the number denoting its depth, first level is 0 (zero), which is also the default, of course. Up to 256 levels are possible. For example: "C:|*" Relative Levels: Multi-script nesting can be defined with relative levels. This can be useful when building menus from local resources by use of the Include statement. Syntax: A relative level is marked by a prefixed "+" character. The number following "+" is added to the last defined absolute level. For example, the following two code samples create identical nested multi-scripts: "A" echo "A"; "A" echo "A"; However, the second sample uses relative levels which allows it to re-use the same part of code twice: "B|||+1" echo "B"; So this part of code could be outsourced to a file say "IncludedMenuBC.xys" and then be included like this: "A" echo "A"; The Goto-Shorthand In a multi-script resource you can pass a plain path/file spec as a shorthand for a well-formed goto script. Such a line will be auto-converted to a valid goto command including the appropriate icon in the generated popup menu. Long version using well-formed goto scripts with captions: "C:\|C:\" goto "C:\"; Equivalent shorthand version: C:\ The goto-shorthand additionally supports environment and native variables, Quick Searches, and visual filters. For example: Desktop Two types of comments are supported, line end comments, and block comments. Line End Comments Line end comments begin with a double-forward slash (outside of any quotes) and end at the end of the line: $a = "<xypath>"; assert $a=="<xypath>"; //should not fail $a = "<xypath>"; //assign XY path "get CountSelected" // comment Block Comments Block comments (aka C-style comments) start with /* (outside of any quotes) and end with the next */ (outside of any quotes) and can span any number of lines: /* This is msg /*they can be inserted anywhere!*/ "hi!" /* anytime */; Remarks on Comments (1) Line-end and block comments overwrite each other: msg "Hi!"; // /*this is not a block comment starting... (2) Make sure you don't nest block comments. It is easy to make this mistake if you are trying to comment out a large block of code: /* This, however, will work since // overwrites the /* */ comment: //msg 'This is a test'; /* This comment is NO problem */ Advancing in script writing, you will soon feel the need for variables. XYplorer allows you to define and use as many variables as you want, using a number of commands like set, input, replace, etc. The script set $a, "Hi!"; msg $a; will define a new variable $a and assign the string "Hi!" (without the quotes) to it; then a message box will display "Hi!". The same can be achieved using the assignment operator (=): $a = "Hi!"; msg $a; Interpolation Variables are resolved wherever they are found in the arguments of all subsequent commands of the script, even if they are found inside double-quoted strings (see below, Interpolation); for example: $name = "Ted"; msg "Hi, I'm uncle $name!"; will display the message "Hi, I'm uncle Ted!". Format and Scope Variables have to conform to the following rules:
Good variables: $a, $ABC, $good_variable, $a1, $a_, $_a, $_ Bad variables: a, ABC, $1, a$, $ä, $., $ Variable names are case-sensitive. The scope and lifetime of a variable begins and ends with the script where it has been defined. Using the equal-operator (=) To assign a value to a variable you can simply use the following syntax (as an alternative for the set command): $a = "b"; or $a="b"; (spaces are ignored) For the additional "reprocess" operand see description of the set command. Increment Syntax (++/--) The common increment syntax using the ++ (--) operator is supported. $i=5; $i++; msg $i; //6 $i=5; $i--; msg $i; //4 $i++; msg $i; //1 You can also use $i++/$i-- as an argument. The value is incremented/decremented after it is passed to the function*: $i = 1; echo $i++; echo $i; //1; 2 $i = 1; echo 1 + $i++; echo $i; //2; 2 $i = 1; echo $i++ + 1; echo $i; //2; 2 $i = 1; echo $i++ . $i++ . $i; //123 Note in the following that the left operand is incremented before the right operand is added. Finally, after the addition, the right operand is incremented: $i = 1; echo $i++ + $i++; echo $i; //3; 3 * Note that before v14.30.0100 the value was incremented/decremented before it was passed to the function! Interpolation Interpolation means that variables that are embedded in double-quoted or unquoted strings are resolved (replaced with their corresponding value). Examples: $name = "Ted"; msg "Hi, I'm uncle " . $name . "!"; Displays "Hi, I'm uncle Ted!". The variable is concatenated with literal strings. $name = "Ted"; msg "Hi, I'm uncle $name!"; Displays "Hi, I'm uncle Ted". The variable is interpolated inside double-quoted literal strings. $name = "Ted"; msg "Hi, I'm " . uncle $name!; Displays "Hi, I'm uncle Ted". The variable is interpolated inside non-quoted literal string uncle $name!. Note that using non-quoted literal strings is not recommended and might even be deprecated in a future version! You can block interpolation by using single-quotes: $name = "Ted"; msg 'Hi, I''m uncle $name!'; Displays "Hi, I'm uncle $name!". The variable is not interpolated inside single-quoted literal strings. Note that single-quotes embedded in single-quotes have to be doubled (I''m). msg '%TMP% = ' . %TMP%; Displays "%TMP% = C:\Temp". The first %TMP% is blocked from interpolation by being embedded in single-quotes. $date = "<date>"; msg '$date = ' . $date; Displays "$date = 28.08.2008 12:23:12". Variables Scope and Lifetime: Local, Global, and Permanent Variables Local Variables By default, all variables in XY scripting are local, i.e. they are not shared between called and calling scripts. In other words, whenever one script calls another script (e.g. using commands "sub" or "load"), a new local namespace is created by the called script and pushed on the stack. Global Variables Generally, global variables are shared between scripts. This can make scripts hard to maintain. However, the mechanism of "globalization" -- (almost) identical to the one used in PHP -- used by XY scripting gives you maximum control over what is shared and where. Global variables are implemented by means of the command global. Permanent Variables The lifetime of local and global variables ends with the current script or script stack. Permanent variables, however, stay alive in memory for the whole XYplorer session, or even across sessions if configured like this (Configuration | Refresh, Icons, History | Remember permanent variables). Hence permanent variables can be easily shared between scripts. Permanent variables are implemented by means of the command perm. Permanent Variables created / modified in a called script are immediately visible / updated in the calling script when the called script returns. Note the scripting commands writepv and readpv by which you can read and write permanent variables from/to file. This allows for some interesting use as portable data storage. To release all permanent variables from memory use the command releaseglobals. You can as well unset them individually via menu Scripting | Permanent Variables directly from the right-click menu in the variable list. To view the current permanent variables use menu Scripting | Permanent Variables. Initial Values Local variables that have never been set to a value return their name as value (strictly speaking they aren't variables but normal strings). Global and permanent variables that have never been set to a value are initialized to "" when they are declared by global or perm: msg $a; // displays "$a" if $a is has not set to any value before, and has not been declared as global or permanent. global $b; // declare global variable msg $b; // displays "" if $b has not been set to any other value before. perm $c; // declare permanent variable msg $c; // displays "" if $c has not been set to any other value before. You can nest expressions using parentheses, aka round brackets: ( ). There's no practical limit to nesting depth and superfluous parentheses are silently removed. Examples where parentheses are merely decor: msg "a" . "b"; msg ("a" . "b"); msg ("a") . ("b"); msg (("a") . ("b")); msg ((("a") . ("b"))); msg "a" . "b" . (); = ab msg "a" . ("b" . "c"); msg ("a" . "b") . "c"; = abc msg "a" == "a" . "a" == "b"; msg ("a" == "a") . ("a" == "b"); = 10 ("1" . "0") Examples where parentheses actually make a difference: msg "a" == "a" . "a"; msg ("a" == "a") . "a"; = 1a msg "a" == ("a" . "a"); = 0 Examples for nesting errors: msg ("a" . "b"; // ')' missing! = ("a" . "b" msg "a" . "b"); // '(' missing! = a"b") Scripting can do basic calculation using math operators +-*/, and also \ (integer division), % (modulo), and ^ (exponentiation). Fractions and parentheses are supported. Also unary operators + and - are supported. Examples echo 1 + 1; echo 1 - 2 - 3; // -4 echo 1 - (2 - 3); // 2 echo 1/3 + 1/3; echo 1 + 2 * 3; echo (1 + 2) * 3; echo 1/0; // ERROR: division by zero $a=3; $b=2; echo $a / $b; // 1.5 $fraction = 1.5; echo $fraction == 3/2; // true echo 1.2 + 2.1; // 3.3 echo 1 + --1; //2 echo --(1 * ----2); //2 echo 5 \ 2; //2 (integer division) echo 5 / 2; //2.5 echo 5 % 2; //1 (modulo) echo 2 ^ 3; //8 echo 4 ^ 0.5; //2 echo 4 ^ -1; //0.25 Remarks
The parser recognizes the common prefix 0x (zero-x) for hexadecimal values. Supported are up to 4 bytes per number, i.e. 8 hex digits. The hex digits are case-insensitive (the prefix is not). Here for some examples; hex values are automatically resolved to decimal values: echo 0xa; //10 echo 0xA; //10 echo 0xFFFFFF; //16777215 echo 0xFFFFFFFF; //-1 echo 0x7FFFFFFF; // 2147483647 echo 0x80000000; //-2147483648 echo 0xA + 0xA; //20 The following are examples for invalid hex strings; they are returned unresolved: echo 0xG; //0xG (invalid value) echo 0x; //0x (no value) echo 0XA; //0XA (wrong prefix) echo 0x123456789; //0x123456789 (too many characters) echo "0x12345678"; //0x12345678 (quoted) Tip: To convert HTML #RRGGBB colors to color decimals use this formula: 0xBBGGRR The parser recognizes the common prefix 0b (zero-b) for binary values. Supported are up to 4 bytes per number, i.e. 32 binary digits. Here for some examples: echo 0b0; //0 echo 0b1; //1 echo 0b11; //3 echo 0b10000000; //128 echo 0b11111111; //255 echo 0b100000000; //256 echo 0b00000000000000000000000000000001; //1 echo 0b10000000000000000000000000000000; //-2147483648 echo 0b11111111111111111111111111111111; //-1 The following are examples for invalid binary strings; they are returned unresolved: echo 0b2; //0b2 (invalid value) echo 0b; //0b (no value) echo 0B1; //0B1 (wrong prefix) echo 0b110000000000000000000000000000000; //0b110000000000000000000000000000000 (too many characters) echo "0b1"; //0b1 (quoted) Comparisons of two values are evaluated in-place. The "comparison" has the general form "a" operator "b" where "a" and "b" are string expressions, and "operator" can be one of the following: == Equal != Not Equal < Less than > Greater than <= Less than or Equal to >= Greater than or Equal to Like Matches Pattern (case-sensitive) LikeI Matches Pattern (case-insensitive) UnLike Does not match Pattern (case-sensitive) UnLikeI Does not match Pattern (case-insensitive) If the comparison evaluates as True it is set to "1", else it is set to "0". Examples msg "a" == "a"; = shows '1' msg ("a" == "a") . ("a" == "b"); = shows '10' $r = ("a" == "a"); $r = ($r?"True":"False"); msg $r; = shows 'True' $comparison = "a == a"; assert $comparison == "a == a"; = no assertion error $minver = "7.60.0009"; assert "<xyver>" >= $minver, "This script needs at least XY $minver!" = no assertion error if XY version is >= 7.60.0009 Strings and Numbers If you compare two numerical strings, they are compared as integers: msg ("2" < "10"); // -> true! (both parts are numeric) msg ("2" < "10a"); // -> false! (only one parts numeric) msg ("2a" < "10a"); // -> false! (both parts are non-numeric) The Like (LikeI) and UnLike (UnLikeI) operators General form: String Like Pattern (case-sensitive) String LikeI Pattern (case-insensitive) Where string is any string expression and Pattern may contain the usual wildcards and special chars used in XY patterns (*?#[]). Note that exact capitalization matters: "Unlike" or "unlike" won't work. These operators must be surrounded by spaces. Examples: echo "abc" Like "a*"; //1 echo "Abc" Like "a*"; //0! echo "Abc" LikeI "a*"; //1! echo "abc" UnLike "a*"; //0 echo "Abc" UnLike "a*"; //1! echo "Abc" UnLikeI "a*"; //0! echo "Abc" LikeI "abC"; //1 (no wildcard!) echo "It's " . ("<date yyyy>" Like "20??"?:"not ") ."the 21st century"; Scripting supports Boolean operators in the following order of precedence (see also Operator Precedence): ! NOT (unary operator) && AND || OR and AND (case-insensitive: AND, And...) xor XOR (case-insensitive: xOR, Xor, XOR...) or OR (case-insensitive: OR, Or...) Examples echo not 1; // 0 echo not 0; // 1 echo ! 1; // 0 echo !1; // 0 echo !!!1; // 0 echo !(1 and 0); // 1 // parsed as: (TRUE and FALSE) or (TRUE and TRUE); // will show "1", then "done" The Boolean constants TRUE and FALSE (case is ignored) are recognized if they are used unquoted. TRUE is resolved to 1. FALSE is resolved to 0. Examples echo TRUE and TRUE; // 1 echo TRUE and FALSE; // 0 echo TRUE and false; // 0 (constants are case-insensitive) echo TRUE and "false"; // 1! (quoted "false" is NOT a constant) echo (1==1) == TRUE; // 1 echo (0==1) == FALSE; // 1 echo (1==1) != FALSE; // 1 Note that in a Boolean context the values "" and "0" evaluate to 0 (FALSE). All other values evaluates to 1 (TRUE): echo "dog" and TRUE; // 1 (TRUE and TRUE)(Boolean context) echo "dog" == TRUE; // 0 ("dog" == "1") (no Boolean context) echo "0" == FALSE; // 1 ("0" == "0")(same strings) echo "" == FALSE; // 0 ("" == "0") (no Boolean context) echo "" XOR TRUE; // 1 (FALSE XOR TRUE) echo "0" XOR TRUE; // 1 (FALSE XOR TRUE) echo "dog" XOR TRUE; // 0 (TRUE XOR TRUE) Note that "0" and 0 ("1" and 1) are the same in XY scripting, so: echo 0 == FALSE; // 1 (0 == 0) echo 0 XOR TRUE; // 1 (FALSE XOR TRUE) Scripting knows so-called "ternary conditionals" as used in many other programming languages. The logic is this: if (condition) { variable = value-if-true; } else { variable = value-if-false; } As ternary conditional the same can be written like follows: variable = (condition) ? value-if-true : value-if-false; The parentheses and the blanks are optional, so these are identical: variable = (condition) ? value-if-true : value-if-false; variable = (condition)? value-if-true: value-if-false; variable = condition?value-if-true:value-if-false; The part "condition" has the form "a" operator "b" where "a" and "b" are string expressions and "operator" can be one of the following: == Equal != Not Equal < Less than > Greater than <= Less than or Equal to >= Greater than or Equal to (none) True if expression is not 0 and not "" The parts "value-if-true" and "value-if-false" are string expressions. Examples $a = "<date hh>" >= "12"? "afternoon": "morning"; msg "Good $a!"; $a = ("<date mm-dd>" == "12-24")? "": "not "; msg "It's $a"."X-mas!"; You can employ ternary conditionals in any argument or part of argument: msg "Good " . ("<date hh>" >= "12"? "afternoon": "morning") . "!"; msg "It's " . ("<date mm-dd>" == "12-24"? "": "not") . " X-mas!"; The Compound Assignment Operators .=, +=, -=, *=, /=, \= can be used to shortcut operations of two variables where the result is set to one of the variables. For example, both lines below are functionally identical; the latter one uses one of the Compound Assignment Operators: $a = $a . "b"; $a .= "b"; More examples: $a = "a"; $a .= "b"; echo $a; //ab $a = 1; $a += 1; echo $a; //2 $a = 1; $a -= 1; echo $a; //0 $a = 2; $a *= 3; echo $a; //6 $a = 5; $a /= 2; echo $a; //2.5 $a = 5; $a \= 2; echo $a; //2 Scripting offers various Control Structures by which you can control the order in which the individual statements are executed. Within these structures blocks of statements are grouped by encapsulating them with curly braces.
General syntax: if (expression) { If expression evaluates to TRUE, the following statement block is executed and the other blocks are ignored. If expression evaluates to FALSE the following statement block is ignored and processing continues with the next Elseif or Else block. Remarks
Examples if (1 == 1) {echo "Hi!"} // shows "Relax." // shows "else", "elseif", "if" General syntax: while (expression) { The nested statement(s) are executed repeatedly, as long as the while expression evaluates to TRUE. The value of the expression is checked each time at the beginning of the loop. If the while expression evaluates to FALSE from the very beginning, the nested statement(s) won't even be run once. Remarks
Examples // will show 1, then 2, then terminate the script // will show 1, 2, 3, then terminate the script // nested while blocks are okay // expression is FALSE, message will never show General syntax: foreach($variable, ListOfTokens, [separator="|"], [flags], [MsgOnEmpty]) { Remarks
Examples // returns 3 strings (moon, sun, venus): // flag r: returns 3 strings in reversed order (venus, sun, moon): // flag e: returns 2 strings ("moon", "venus"); empty items are skipped: // nested foreach loops // selected list items // shows "No files selected!" if no files are selected, and skips the loop // passing an empty separator = tokenize by letter The switch statement is similar to a series of IF statements on the same expression. In many occasions, you may want to compare the same variable (or expression) with many different values, and execute a different piece of code depending on which value it equals to. This is exactly what the switch statement is for. In a switch statement, the condition is evaluated only once and the result is compared to each case statement. In an elseif statement, the condition is evaluated again. If your condition is more complicated than a simple compare and/or is in a tight loop, a switch may be faster. General syntax: switch (n) { Remarks
Examples // switch The switch and case arguments can also be more complex expressions: $a = 3; $b = 7; $c = 10.5; $d = 2; Usually each case should be closed by a break statement. Else processing continues with the next case (sometimes though this can be desired). Here is an example where omitting break statements makes sense. Also shows that the default case also accepts a break statement (although is totally superfluous here). Also shows that semicolons after the cases are an acceptable alternative to colons: $beer = 'Kirin'; The case statements don't have to be in their own line. This example also shows that using the return command within a function you can spare the break command: function getChineseZodiac($year){ Also note this somehow perverted use of a switch: $a = "Kirin"; Heredoc, using the <<< operator, is a way to define multi-line strings "as is" without the need to escape quotes etc. The rules follow the PHP rules for Heredoc:
Within the Heredoc section:
Example A multiline script using Heredoc. Note that the Heredoc block is not indented, that comments are not removed, that quotes are not doubled, and that the variables are resolved (the only difference to Nowdoc), even within comments. Basic example: $str = <<<EOD More complex example, with variables and comments: $name = "Bond"; Output: My name is Bond, "James Bond". // line end comment: Bond Alternative Heredoc Syntax A more radical parsing where the ending identifier can be anywhere is enabled when the identifier starts with a "#". These examples show two ways to code the same script. $isOk = Confirm (<<<#FOO With the old-school parsing the ending identifier must be on its own line: $isOk = Confirm (<<<FOO Nowdoc Syntax A special variety of Heredoc is the Nowdoc, that is a Heredoc without interpolation. Quoting from PHP Documentation: "Nowdocs are to single-quoted strings what heredocs are to double-quoted strings. A nowdoc is specified similarly to a heredoc, but no parsing is done inside a nowdoc. The construct is ideal for embedding PHP code or other large blocks of text without the need for escaping. It shares some features in common with the SGML <![CDATA[ ]]> construct, in that it declares a block of text which is not for parsing. A nowdoc is identified with the same <<< sequence used for heredocs, but the identifier which follows is enclosed in single quotes, e.g. <<<'EOT'. All the rules for heredoc identifiers also apply to nowdoc identifiers, especially those regarding the appearance of the closing identifier." Example: $var = "syntax"; Output (note that $var has not been resolved): Example of string Nowdoc also accepts the alternative radical option (see above) enabled by prefixing the identifier with '#' (within the quotes). You can use the dereference operator * (asterisk) with all variables. Usage: Helpful when dynamically creating variables. Examples $var = '$a'; *$var = "TEST"; echo $a; //TEST $var = '$a'; perm *$var = "TEST"; echo $a; //TEST $var = '$a'; global *$var = "TEST"; echo $a; //TEST $var = '$a'; *$var = "TEST"; echo "*$var, $a!"; //TEST, TEST! If the dereferenced variable is not defined, then the variable itself is used (as if there was no dereference operator): *$undefined = "TEST"; echo $undefined; //TEST Note that also unset and incr support the dereference operator: $var = '$a'; *$var = "TEST"; unset *$var; echo $a; //$a $var = '$a'; *$var = 1; incr *$var; echo $a; //2 $var = '$a'; *$var = 1; *$var++; echo $a; //2 $var = '$a'; *$var = 1; *$var--; echo $a; //0 $var = '$a'; *$var = 1; echo 1 + *$var++; echo *$var; //2; 2 Not in Interpolation Dereferencing does not take place in interpolation. Compare the following scripts. Only in the last one $a is dereferenced: $a = '$b'; $b = "Test"; echo "*$a!"; //*$b! $a = '$b'; $b = "Test"; echo *$a!; //*$b! $a = '$b'; $b = "Test"; echo "*$a"; //*$b $a = '$b'; $b = "Test"; echo *$a; //Test Also in these scripts using HEREDOC $a is not dereferenced but resolved to "$b": $a = '$b'; $b = "Test"; echo <<<FOO $a = '$b'; $b = "Test"; echo <<<FOO The precedence of an operator specifies how "tightly" it is connected to its surrounding operands. For example, in the expression 1 + 2 * 3, the answer is 7 and not 9 because the multiplication ("*") operator has a higher precedence than the addition ("+") operator. Parentheses may be used to force precedence, if necessary. For instance: (1 + 2) * 3 evaluates to 9. The following table lists the precedence of operators with the highest-precedence operators listed at the top of the table. Operators on the same line are evaluated from left to right (3 - 2 + 1 evaluates to 2, not 0): Operators Additional Information ------------------------------------------- ++ -- Math: Increment, Decrement ! Not Boolean: NOT + - Math: Unary Plus, Unary Minus (operator is prefixed to a number) * / *= /= Math: Multiply, Divide % Math: Modulo \ \= Math: Integer division + - += -= Math: Add, Subtract . .= String concatenator < <= > >= == != Comparison Like LikeI UnLike UnLikeI Comparison && Boolean: AND || Boolean: OR And Boolean: AND Xor Boolean: XOR Or Boolean: OR ? : Ternary = Set *** For software developers only *** You can run an XYplorer script from an external program using the WM_COPYDATA command with XYplorer's hWnd. This means if you are a programmer you can fully remote control XYplorer.
Like other aspects of XYplorer scripting also user-defined functions are closely modeled after PHP. A user-defined function (or simply "user function") is a block of statements that can be used repeatedly in a program. It can return a value (using the command "return"). The function declaration starts with the word "function", then a space, then the name of the function: General form: function functionName() { Alternative formatting: function functionName() { code to be executed; } Example with 2 arguments and a return value: function sum($x, $y) {
Example 1: Arguments and Returns echo multiply(3, 4) . <crlf> . sum(11,12); Example 2: Argument by Value $a = 1; add_one($a); echo $a; //1 Example 3: Argument by Reference $a = 1; add_one($a); echo $a; //2 Example 4: Argument with Default Value echo multiplyDefaults(2); //8 (2 * 4) The "include" statement lets you include the content of a file at the place where the "include" statement was found. That way you can include e.g. function libraries into your script resources. Note that the "include" statement is evaluated unconditionally when a script resource is loaded and before anything else is done. Syntax include file; file: Path, if not fully stated, is resolved relative to <xyscripts>. Extension defaults to ".xys". Quotes are optional (they are totally function-less here, but might look better to some folks including me). Note that you cannot use any script variables for file. However, XYplorer variables and environment variables are supported. Remarks You may end any include statement line with the usual instruction terminator ";". However, you must not append other instructions in the same line. The include statement needs to have its own line. |
XYplorer-
最新推荐文章于 2025-03-22 09:29:38 发布