The Plugin Library allows Selected Library Functions to be accessed. The most important is shown in {LIB func='libAddAnchorLink' anchor='libAddAnchor' txt='Example 1' } {/LIB} which deals with Anchors and Links to them. At this point - all of the remaining Examples demonstrated different kinds of Boxes.
Why Not Just Create Plugins?
The answer is time! Each and every Plugin requires a significant amount of time spent in it's creation / writing and rewriting the help / debugging / etc. A Library Function and this Plugin provide an alternative. Adding Simple functionality can be accomplished very quickly in a Library Function. Providing Users with access to it (this Plugin) can also be accomplished very quickly. A large percentage of our existing Plugins could be replaced with Library Functions. I'm only stating a fact - Not making a suggestion or volunteering. Plugins are still needed - but the complexity required should be the governing key. Another issue is - at this time - the functionality provided by Library Functions can not be controlled (turned off) like a Plugins can be.
How Does It Work?
This Plugin functions like every other Plugin even though the Library Functions define most of the Parameters. In this example only the Parameter func is defined by the Plugin.
{LIB func='libHeaderBox' header='My Header' }Life is Grand!{/LIB}
{LIB func='libHeaderBox' header='My Header' }Life is Grand!{/LIB} The specifics of each function is defined in the next heading: The Plugin's Help.
Between The Code Blocks? {LIB func='libAddAnchor' anchor='Between The Code Blocks' } {/LIB}
For those of you who don't know - the term Code Block refers to the way a Plugin is called. Some Plugins only require a single Code Block to operate while others need two. Examples are:
{AGENTINFO info= } requires a Single Code Block while
{CODE source= num= }Source Code{/CODE} requires Two Code Blocks. The first is {CODE source= num= } and the second is the closing {/CODE}.
Most Plugins that require 2 Code Blocks do so because they expect a lot of data and are designed to work on it. They use Parameters to control what they do to the data between the Code Blocks. The Plugin Library does this as well. That allows all of the boxes to contain as much data as you want to place into them.
These functions work together to add Anchors and Links to them. For those of you who don't know - an Anchor is a marker that allows you to jump to it. The best example of this are the Links located in the Table of Contents which are created with {maketoc}. Unlike the Anchors created for the Table of Contents (which use a Visible Header to define them) - Anchors created by libAddAnchor do not need to be visible and are not normally displayed in the Table of Contents. As an example, the Top and Bottom of this page (and all of the Examples) have Anchors created with libAddAnchor. This is what the calls look like:
Adding a Link to an Anchor is accomplished with libAddAnchorLink like this (be sure you use the same Anchor Name with both functions):
{LIB func='libAddAnchorLink' anchor='PageTop' txt='Top of Page' } {/LIB}
{LIB func='libAddAnchorLink' anchor='PageBottom' txt='Bottom of Page' } {/LIB}
-->{LIB func='libAddAnchorLink' anchor='PageTop' txt='Top of Page' } {/LIB}<-- -->{LIB func='libAddAnchorLink' anchor='PageBottom' txt='Bottom of Page' } {/LIB}<--
That does not mean that the Anchors created by libAddAnchor have to be invisible or that they can not be displayed in the Table of Contents. At times a visible Anchor can come in handy - even if they don't Do anything. This creates a Visible Anchor:
{LIB func='libAddAnchor' anchor='A libAddAnchor Header' level='3' } {/LIB} This Anchor looks like a normal Header and it is included in the Table of Contents.
Example 2 - libBox {LIB func='libAddAnchor' anchor='libBox' } {/LIB}
This Box is almost identical to the function libHeaderBox. The only difference is that a Plus/Minus Icon is located in the Header which Expands/Contracts the Message Section of the Box.
{LIB func='libContractedHeaderBox' header='This is the Header' }And this is the Message{/LIB}
{LIB func='libContractedHeaderBox' header='This is the Header' }And this is the Message{/LIB} I hope this a little closer to what your looking for? Hay - I'm trying!
Example 6 - libTabBox {LIB func='libAddAnchor' anchor='libTabBox' } {/LIB}
Did I mention that I like Tab Boxes? This is the same Tab Box created with the function libTabBox except the Message area can be Expanded/Contracted.
{LIB func='libContractedTabBox' title='My Tab' }And this is the Message{/LIB}
{LIB func='libContractedTabBox' title='My Tab' }And this is the Message{/LIB} If you haven't found that big thing yet - you never will! It just doesn't get any better than this.
This Plugin does a lot or error checking and produces a lot of very similar Error Messages - depending on what was done wrong. Here are a couple of examples:
{LIB func='libBadFunctionName' } {/LIB}
{LIB func='libBadFunctionName' } {/LIB} Obviously - you can't expect a function that doesn't exist to do anything except give you an Error Message.
Final Thoughts
This page demonstrates how simple functions can be added to provide a User with Options! These functions are fairly simple and didn't take a long time to create. Almost nothing in comparison to a Plugin - so as time passes - I think there will be a lot more of them. In any case - Enjoy StarRider (s-r on IRC) {LIB func='libAddAnchor' anchor='PageBottom' } {/LIB}
{LIB func='libAddAnchor' anchor='PageTop' } {/LIB} {COMMENT } 1- Please use this format when adding new examples 2- Every Library Function needs an Example xxx - FunctionName Anchor combination as shown. I will admit that adding an Anchor to a Heading looks strange but on this page it is unavoidable. That is because the Help for { LIB } provides a link to this page with an Anchor - so the Anchor need to be findable - which is not the case when they are inside a Contracted Header.
Example x - libFunctionName {LIB func='libAddAnchor' anchor='libFunctionName' } {/LIB}
{LIB func='' p1= p2= p3= } {/LIB} Explain what is special about it {COMMENT}
Introduction
The Plugin Library contains a lot of small, self-contained functions that are designed to do specific tasks. Some of them are useful to a User. This Plugin provides a Gateway to those functions.
This Plugin came about almost by accident. While working on another Plugin I had a function naming conflict and realized that any function defined in a Plugin is global in nature. Since a large percentage of the code in a Plugin is repetitious - a library of functions could reduce a lot of repetitious code. Further - it could eliminate a lot of time in the development of a new Plugin while increasing their functionality. A Library was created and I started converting the Plugin I was working on to use it. A little later - I realized that some of those functions could be useful to a User. I decided to create the Plugin to make that happen but the main question was - where was the extra information needed going to come from. There were several options but I wanted maintain the same methodology used everywhere else in bitweaver. By that I mean that nothing could be hardwired. Additions or modifications to the Library had to be automatically included. With Plugins this is done with a registration process that works quite well - but I didn't want all of the overhead that this would require. There was also a Page Space problem that had to be addressed. We have a Lot of Plugins and their Help and Parameter Data take a Lot of space. This Plugin would only make matters worse because each Function would need a Description and it’s own set of Parameter Data. I had a discussion about this on IRC with Xing a couple of months before but I think he was too busy to fully understand what I was talking about. In any case - I wanted to make some improvements of my own. The Communication Problem didn't prove too be as difficult as I thought it would be - but in solving it I found another problem: Error Testing. In a Plugin - every Parameter a User enters has to be validated for existence and then converted to the proper type for usage. That isn't a big thing in a Plugin - but doing it in each and every Library Function would have defeated the reason for creating the Library in the first place. Obviously - this Plugin would have to do the Error Testing for every Library Function - which provided the excuse I needed to create several more generic Library Functions. I knew how to make the Load Function work - but it was the Help Function that proved to be the most troublesome. I created an Array in the Library that contained all of the necessary information (and it just kept growing). The Library was Global - Right? Not to Arrays! I don't know how many days I spent trying to find a way to access that Array (and I probably wouldn't admit it if I did) - but every approach I found simply didn't work. Upset? That's putting it mildly! I felt like a bloody failure so - I tried to Cheat! My Load Function basically builds a Library Function call in a string and then executes it. So why couldn't I do that with the Array? What I needed was a way to convert a Multi-Dimensional Associative Array to a String that could be then be used to recreate the array. It took a lot of time but I got exactly what I wanted - it works beautifully - but there was a problem. Stupid quotation marks! Adding a single quotation mark like this - It's about time - would cause it to crash big time. The worst part was that it always gave the same error message - not very helpful. Scratch that idea! Eventually - I expanded the LibertySystem a little and added a couple more methods. In the process of getting the kinks out of the Help Function (it is very different from the average Plugin) - I solved the Page Space problem by changing the way the Plugin's Help is displayed. Of course that meant modifying the Plugin PluginHelp to make it look the same. I don't mind saying that I think they are pretty slick now. I thought I was finally finished and was writing this page when I realized something that stopped me cold. Most of the Library Functions accessed by this Plugin are Boxes and the Plugin was using requires_pair set to False! That meant that all of the data sent to those boxes had to be placed in parameters. For a Box that would be very limiting. Sounds like a minor inconvenience - Right? Ha! - I thought so at first. I saw an easy solution and made it work - but the more I thought about it - the less I liked it. It required the user to specify where the data was coming from. Clunky! I knew I was going to make the changes to do it right - even if that meant changing everything. It wasn’t quite that bad - but it forced me to rewrite my load function from scratch.