===== Creating user libraries ===== Libraries are a way to package and distribute a group of programs or data for others to use. They can be accessed from the **Lib** menu, which shows all currently installed libraries. Initially, the **Libs** menu is empty until libraries are installed. ==== Installing / removing a library ==== Libraries are regular RPL objects and therefore can be transferred to the calculator via the [[manual:chapter4:usb|USB port]] or [[manual:chapter4:card|SD card]]. To enable the functionality of a library on the system, put the library object on the stack and use the ''[[manual:chapter6:libptr:cmd_attach|ATTACH]]'' command (it can be found on the **MAIN** menu under submenu **System** / **Lib**, not to be confused with **Libs** which shows the installed libraries). If the ''[[manual:chapter6:libptr:cmd_attach|ATTACH]]'' command succeeds, it will leave on the stack a 4-letter //library ID//, and a string with the library description. The library ID is a unique name the developer assigns to the library, and is how the library shows up in the **Libs** menu. From that moment on, any commands exposed by the library will become available to use in programs or directly from the corresponding submenu in the **Libs** menu. To remove a library that was previously installed, use the command ''[[manual:chapter6:libptr:cmd_detach|DETACH]]''. The command takes a library ID in the form of a 4-letter identifier, which can be retrieved directly from the **Libs** menu using **RShold-[menu key]** while in Alpha mode. To confirm that a library was successfully detached, check that its library ID no longer appears in the **Libs** menu. ---- ==== Creating a new library ==== User libraries are created by putting in a separate directory all the programs and data the library needs to carry. Some additional data is necessary and has to be provided in specially named variables that will be analyzed in detail next. Once all the information is there, the command ''[[manual:chapter6:libptr:cmd_crlib|CRLIB]]'' executed from within the library directory will produce a proper library object and leave it on the stack. The original source directory is left unmodified. === $LIBID === It contains the library ID that will identify the library. The library ID is an identifier up to 4 letters or numbers, with the first character being a letter. The only allowed characters are ''A''-''Z'', ''a''-''z'' and ''0''-''9''; if any other characters are included or if the length exceeds 4 characters ''[[manual:chapter6:libptr:cmd_crlib|CRLIB]]'' will issue an invalid library ID error. === $TITLE === It contains a string with a title/description or copyright message of the library. It has no purpose other than being shown to the user when the library is attached, or when the help is invoked on the **Libs** menu by long-pressing on the library name. === $VISIBLE === It consists of a list with information about the commands that will be exposed to the user. Any commands not in this list will not be visible to the user, and unless called from one of the visible commands, they won't be bundled with the library either. The list has to follow a specific format: { { } ... } where * '''' is the name of the command to be made visible: this is both the name of the variable containing the command in the directory, and the name of the command as it will be seen by the user of the library; * '''' is an integer numbers representing the number of arguments that the command takes from the stack; * '''' is a true/false value (1 or 0) indicating whether that command will be allowed to be used in symbolic expressions or not. All user commands (when allowed by setting this number to 1), will be accepted as a function call inside expressions, and the number of arguments will be checked against the '''' number; * '''' is a string to be used as help when the user long-presses the name of the command in the menu. The string should be formatted so the text is in 3 lines, with the first 2 describing the command and the third line shows a stack diagram (preferably following the same guidelines as used in the system menus for consistency). ''$VISIBLE'' must therefore be a list of lists, where each sublist has exactly 4 elements: one ident, two integers and one string. Any deviation from this format will cause ''[[manual:chapter6:libptr:cmd_crlib|CRLIB]]'' to issue an ''Invalid $VISIBLE list''. === $MENU === This is an optional variable: the ''[[manual:chapter6:libptr:cmd_crlib|CRLIB]]'' command will automatically create a menu with all the visible commands in the same order as listed in ''$VISIBLE''. If the library requires other types of menu, a [[manual:chapter7:custmenu|complete menu definition]] can be included in ''$MENU''. If a custom ''$MENU'' is given, the '''' field given in ''$VISIBLE'' is simply ignored (the help must be provided as part of the custom menu), but cannot be omitted: an empty string ''""'' can be used in this case. === $IGNORE === This is an optional variable: in some cases there might be data or programs in the library directory that should not be included with the library, even though they might be referenced by the library commands (this is uncommon but could happen). This optional list of identifiers tells ''[[manual:chapter6:libptr:cmd_crlib|CRLIB]]'' to never bundle these variables with the library. ---- ==== A sample library: HWORLD ==== This library will have a single command ''HWORLD'' that puts the message "Hello world!" on the stack. To create it, first create an empty directory: 'helloLIB' CRDIR and go into it, then create the program and the special variables inside the directory: ^ Variable ^ Content ^ | ''HWORLD'' | ''« "Hello " WORLD + »'' | | ''WORLD'' | ''"world!"'' | | ''$LIBID'' | '''MyHW''' | | ''$TITLE'' | ''"My Hello World Library!"'' | | ''$VISIBLE'' | ''{ { 'HWORLD' 0 0 "Shows a nice↲greeting.↲ → " } }'' | Finally, use ''[[manual:chapter6:libptr:cmd_crlib|CRLIB]]'' to create the library, then ''[[manual:chapter6:libptr:cmd_attach|ATTACH]]'' to attach it. From the **MAIN** menu, **Libs** will now show a new item **MyHW**. Long pressing the item will show the library title. Going into the menu we should see the ''HWORLD'' command, long pressing it will show the help that was provided. Notice that in this case, the ''WORLD'' variable is included in the library because it was referenced by the main program ''HWORLD'', but it is not visible to the user since it is not listed in ''$VISIBLE''. From now on, compiling a program that contains ''HWORLD'' will use the installed library command, rather than an identifier. Programs compiled before the library was attached will have an identifier instead. ---- ==== Using CRLIB ==== The ''[[manual:chapter6:libptr:cmd_crlib|CRLIB]]'' command works in a complex way, and understanding how it works helps the developer plan ahead the organization of the library to make sure things work well. The most important points that need to be considered when writing a library are: * don't use subdirectories. Every single object to be included in the library must be in the current directory when ''[[manual:chapter6:libptr:cmd_crlib|CRLIB]]'' runs. It does not look for objects anywhere else;\\ \\ * name visible commands exactly as the user will see them;\\ \\ * other (non-user-facing) subroutines can be included in the same directory, their names don't matter. ''[[manual:chapter6:libptr:cmd_crlib|CRLIB]]'' will scan every program included in the ''$VISIBLE'' list for variables and subroutines. If found in the library directory, their names will be replaced with internal library pointers and their contents included in the library.\\ \\ It is important that ''[[manual:chapter6:libptr:cmd_crlib|CRLIB]]'' only includes programs or data recalled by using unquoted identifiers. For example when the program ''« MyMatrix INV »'' is scanned by ''[[manual:chapter6:libptr:cmd_crlib|CRLIB]]'' two things can happen: either the identifier ''MyMatrix'' is found in the library directory (its contents included with the library and if a program, later scanned as well) or ''MyMatrix'' is not found, in which case the identifier will be left as-is;\\ \\ * quoted identifiers or other forms of calling programs will **not be recognized** by ''[[manual:chapter6:libptr:cmd_crlib|CRLIB]]''. For example, ''« 'MyMatrix' RCL INV »'' will do the same as before when executed outside the library, but ''[[manual:chapter6:libptr:cmd_crlib|CRLIB]]'' won't look for ''MyMatrix'', and won't add it to the library: the explicit use of ''[[manual:chapter6:dirs:cmd_rcl|RCL]]'' indicates the intent of reading the current directory, rather than recalling an internal library object/program;\\ \\ * write your code as you would use it from the source directory, remembering that if your code stores something temporarily in the directory and uses it by name using an unquoted identifier, you should ''[[manual:chapter6:dirs:cmd_purge|PURGE]]'' it before calling ''[[manual:chapter6:libptr:cmd_crlib|CRLIB]]'' or it will be included with the library. As an alternative, you can put its name in the ''$IGNORE'' list, and ''[[manual:chapter6:libptr:cmd_crlib|CRLIB]]'' will not include it.\\ \\ * private library settings can be stored and recalled using ''[[manual:chapter6:libptr:cmd_libsto|LIBSTO]]'' and ''[[manual:chapter6:libptr:cmd_librcl|LIBRCL]]''. These two commands will work the same as ''[[manual:chapter6:dirs:cmd_sto|STO]]'' and ''[[manual:chapter6:dirs:cmd_rcl|RCL]]'' when called from the source directory, but when executed from within a library command, they will store/recall content from a __special hidden directory__ that is private to the library. Each library can store arbitrary data in this private directory. Data is persistent and can only be erased by calling the ''[[manual:chapter6:libptr:cmd_libclear|LIBCLEAR]]'' command. Data stored with ''[[manual:chapter6:libptr:cmd_libsto|LIBSTO]]'' can only be recalled with ''[[manual:chapter6:libptr:cmd_librcl|LIBRCL]]'': using the unquoted name won't work since the variable is not in the current directory or local variable environment.\\ \\ * after testing a library, remember to ''[[manual:chapter6:libptr:cmd_detach|DETACH]]'' it before trying to edit its code in the source directory. Remember that the variables are named exactly like the library commands, and if the library is attached, those names will be compiled to call the installed library, rather than the intended name identifier. This will not be visible to the user, the code will look identical but ''[[manual:chapter6:libptr:cmd_crlib|CRLIB]]'' will not be able to scan the names to include the subroutine.\\ \\ * when extending a library with new commands, always add entries **at the end** of the ''$VISIBLE'' list. People using your library will have their own programs compiled with library pointers, which internally use the library ID and the index into the ''$VISIBLE'' list to refer to your commands. If the order of the commands change on the new version, user programs compiled for previous versions of the library will call the wrong command. If desired, create a custom ''$MENU'' to organize the commands in a different order as ''$VISIBLE''.