Thursday, November 4, 2010

PEM Editor Tip: Creating your own Dynamic Snippets

Custom Dynamic Snippets are defined by creating PRGs in a particular folder.  The PRGs take a single parameter, return a simple result, and are generally stand-alone.  There is a template snippet that you can rename and edit as needed for new snippets.  Reading (or modifying) existing snippets would, of course, be of great assistance in seeing how they work.

The PRG files that PEM Editor looks for are named PEME_Snippet_*.PRG, where the '*'  matches the name of the snippet-keyword that the PRG handles.  The PRGs may be in the current directory, anywhere in the path, or in the sub-folder (named 'Dynamic Snippets') of the folder where PEM Editor is installed.

There are a number of sample PRGs in a sub-folder (named 'Snippet Samples'). These samples include the exact code used for the Dynamic Snippets that are built in to PEM Editor. All of these samples can be activated simply by copying the entire contents of the Samples folder into the parent folder ( 'Dynamic Snippets').
Dynamic Snippets have been designed in such a way that it is simple both to perform the desired task and also to publish its description (that is, what you see from @Help).  There are three distinct sections in each PRG:

First Section: Compile-Time Constants:  Four constants which identify the snippet-keyword, and how the remainder of the snippet is to be split into parameters for the 'Process' function (see below).  These identify the delimiter between parameters, and the minimum and maximum number of parameters that are acceptable.

Middle Section: Setup and Cleanup Block: A block of code that handles passing of parameters, etc.  Skip this; it shouldn't be changed.

Last Section: Custom code for this snippet: This section, at the very end of the PRG, contains the following two functions: 

Function 'Process', which is called if the snippet-keyword for this PRG matches the keyword that was entered in the code window.  This is the procedure that you will modify to actually do the work of the snippet.

The text following the snippet-keyword will have been broken into a list of parameters, and this function is called with these parameters, as character.  The result is to be one of:
  •  a character string -- which will replace the snippet entered in the code window.  The sub-string '^^^' is used to indicate where the cursor is to be placed.  (The default is to place the cursor after the inserted string.)
  • .T. -- if the string was handled by the PRG, but the Snippet entered in the code window is not to be touched.  (See, for instance @Sel, which modifies the code window itself and then places the cursor appropriately)
  • .F. -- if the string was not handled by the PRG
A simple example of this is found PEME_Snippet_UC.PRG, which creates a case-insensitive comparison of two strings.  Here is all the code:
* Top Section
    #Define Snippet_Keyword     UC
    #Define Delimiter_Char      '='
    #Define Min_Parameters      2
    #Define Max_Parameters      2
  
    * Bottom Section
    Function Process
        Lparameters lcText1, lcText2
        Return 'Upper(' + lcText1 + ') = Upper(' + lcText2 + ')'
    EndFunc

Function 'PublishHelp', which is used to publish the syntax, summary, and detailed explanation that appear in @Help. 

Additional Notes:
There aren't really any limitations to what you do within the procedure 'Process'.  You can add procedures and funtctions to the PRG, call dialogs, open external forms, etc.  You can also modify the text in the code window directly, using _oPEMEditor.oEditorWin, which is an object containing cover functions for the tools in FoxTools.fll.  (Documentation on this is not yet available.)

To simplify the task of debugging snippets, you can invoke directly them, even if PEM Editor is not running..  Just call them with a single parameter, equivalent to the character string which follows the snipper-keyword..  The result should be the replacement character string.  Once they work correctly when invoked directly, they should also be available for immediate use as a Dynamic Snippets.

No comments:

Post a Comment