CRiSP File Editor Programmers Guide Version 6 © 1998 Foxtrot Systems Ltd www.pacemaker.co.uk sales@pacemaker.co.uk fox@crisp.demon.co.
Introduction 7 Disclaimer 7 Getting started with Macro programming 7 An Overview of the Programming Facilities 8 Writing your own macros 9 Tools Overview crtags: cross-referencing source files File formats Specifying Directories Language Mapping switches General switches Filename filtering Output file format Language specifications" Language element feature selection Languages 10 10 11 11 11 11 12 12 13 13 13 The CRUNCH Language 14 The crunch compiler 14 Data types 15 Variables - types, sc
List assignment 23 Making Lists 23 Manipulating List Items 24 Sorting Lists 24 Searching Lists 24 Informational Lists 24 The declare datatype 25 Structures 25 Language Grammar 25 Declarations 26 Function definitions 27 Loading a macro: main, _init 27 Expressions 27 Loop constructs: for, while, do 28 Testing expressions: if 29 Selection: switch 29 Debugging macros 30 Primitives for showing output 30 Macro tracing 31 Debug applied to a function 32 Debug on startup 32
Current cursor position 35 Modified Flag 35 Permissions & Read-only Flag 35 Process Buffers 36 Region Markers 36 Symbol Table 36 System Buffers 36 Tab Settings 36 Undo Information 36 Character Maps 37 Objects supported by CRiSP 38 File Types -- Text files and Binary Files Backing up Files Autosaving Core dumping Regions and markers 39 39 39 40 40 Macros Global and Static macros Modules and static macros 41 41 42 Registered Macros 42 Timer functions 45 Color Support 46 Searchi
GUI Based Objects 51 Terminology 52 Windowing Systems Programming 52 Overview of the Dialog box system 53 Overview of an Object 54 Creating a Dialog Box 55 Object Types 56 Geometry Layout 59 Resizing dialog boxes, and Constraint management 60 Object hierarchies: menu bars, tool bars, status panels 62 Object hierarchies and grouping 63 Sub-groups 64 Groups and the DBOX_CONTAINER object 65 Properties (private symbols) 65 Dialog boxes and Callbacks 66 Platform Specific Issues 67
Case study #2: Fortran colorizer Interprocess Communication and CRiSP 78 79 IPC Mechanisms 79 IPC Primitives 80 IPC Callbacks 80 TCP/UDP Communications 81 Pipe Communications 84 PTY Communications 84 DDE Communications 85 Signals Communications 86 Keyboard objects 87 CRUNCH: Things to watch out for 90 The cm compiler 90 Page 6
. Introduction Document version: 1.002, date 24 November 1997 This guide discusses how to write macros in the CRiSP extension language, known as CRUNCH. The CRiSP software package is a highly flexible file editor for use by people who need to edit files, whether they be programmers, or engineers. CRiSP is designed to be easy to use and have a familiar user interface. Underlying all this power is a powerful macro language which implements the things you use and see in the user interface.
# include void mymacro() { message("This is my macro!"); } The #include statement is something you will need sooner or later in the macros you write. Although it is not needed for this simple macro, you may need it as you extend your macro. The crisp.h file contains numerous constant definitions which you need for some of the builtin functions of CRiSP. This macro file contains a single macro, called mymacro. You can execute this macro after you have compiled and loaded the macro.
→Writing your own macros(pg. 9). →The .m language(pg. 90). →The crunch language(pg. 14). Writing your own macros Private macros can be loosely categorized into two types: small one-off macros which are used to make some piece of functionality easier to use (e.g. mapping certain editing commands to special keystrokes), or major projects in their own right.
the usability features of CRiSP but also contain useful real-life examples of various aspects of CRiSP macro programming. 3. Where possibly, try and maintain a macro programming style. Do not write throwaway macros - treat them with respect. For example, format them nicely, comment them, lay them out well. You will find it so much easier to revisit your macros at a later date, or if you need to pass them on to people, they will actually understand your code.
crtags [switches] file1 file2 .... You can use Unix style wild cards for the filenames, even on the Windows platforms. The command line switches can be grouped into three types: - general purpose switches affecting the crtags program, - output file format switches - language sensitive element switches File formats crtags creates a tags file. Two file formats are supported: text and binary.
included on the command line. This allows you to generate a list of files and store them in a file rather than being exposed to the command line limitations of certain operating systems. Multiple -I switches can be specified on the command line and can be intermingled with normal files. If you use this switch is must be the last switch on the command line. -ignorecase When sorting the tags file during the output stage, ignore the case of data elements.
These switches allow you to specify the output file format. -tags Output is compatible with the Unix ctags program and hence the tags database can be used with other editors such as vi. -text Output file in textual format. Useful for diagnosing the output. -crtags (Default) Proprietary file format designed to be used in conjunction with CRiSP.
SQL TeX Perl Verilog VHD Yacc grammars .sql .tex .pl, .pm .v, .verilog .vhd, .vhdl .y Note that crtags uses a fuzzy-parsingfuzzy parsing mechanism to scan source files. This has the advantage of working in spite of any syntax errors and avoids the complexity of worrying about compile-time constant definitions which may affect the flow of the parsing (e.g. in the presence of #ifdef constructs). The down-side of this is that the parsing may not be 100% correct as seen from the point of view of the compiler.
ready for loading into CRiSP. The crunch program uses its own internal preprocessor which is very ANSI-C like. By doing this gives the user more portability of macros and avoids common differences between standard preprocessors. Next the intermediate file is converted directly to the binary output file. Crunch has a number of switches: -c Compiles the source file to a .m file. This is useful for understanding the translation process or to check for bugs in the compiler.
int(pg. 21). 32-bit signed integer. float(pg. 21). 64-bit floating point value. string(p g. 21). Variable length string. list(pg. 22). Arbitrary collection of objects, similar to an array. Lists may contain nested lists, and can be used like a structure or array. declare( pg. 25). Used to define a polymorphic variable - one that can contain a value of any type. As well as these primitive data types, CRiSP also supports complex data types(pg. 38).
{button See Also, ALink(crunch,,,)} Scoping All variables created have a scope of visibility. CRiSP supports a number of scopes of visibility: static, local, global and buffer-local. Global variables are always available to macros and retain their values from one function to another. Local variables exist from the point at which they are defined to the end of the current block. The current block is defined as the current level of curly brackets.
not found, CRiSP then searches the current block level - 1. At this block level, the definitions are found. When a variable is accessed, CRiSP needs to locate the symbol definition dynamically. The order of processing is as follows: 1. First a check is made for a static variable definition in the current function. 2. If no value is found as a buffer local variable, then CRiSP will try the current local variables of a function. 3.
int sum() { int int int arg_no = 0; sum = 0; arg; while (get_parm(arg_no, sum) > 0) sum += arg; return sum; } Crunch performs limited prototype validation and this is designed to catch inconsistent coding errors. You should therefore always specify prototypes for external functions so that CRUNCH can check that arguments agree. (CRUNCH cannot perform a complete type-safe check because variables can be declared as polymorphic, in which case the type of variable will not be known until run-time).
Variable argument lists CRiSP supports a variety of mechanisms which allow for variable numbers of arguments to be passed to macros. As described above the get_parm() and put_parm() primitives are used to access arguments to macros. A useful addition to these primitives is the arg_list() primitive. This primitive returns a list representing the arguments passed to the calling macro.
{ d = max(a, b, c); } Note the ampersand after the type specifier for the last parameter in the list. Variables which are passed by reference are noted by the crunch compiler and any assignments to these variables cause the right thing to happen, i.e. the callers argument is updated. The pass by reference mechanism shown above is actually implemented using the lower level put_parm() primitive. Put_parm() is a special macro primitive which lets you assign values to the calling functions parameters.
string length. string:definition Storage for strings is dynamically allocated so no space needs to be preallocated for them. Strings may be combined with the other data types to perform concatenation. String constants are specified by enclosing the string within double quotes. For example "the help text" You can include a double quote character by quoting it with a backslash as in: "Select the \"Help\" button for more help" You can use the backslash character to quote the meaning of the next character, e.
The following sections describe various aspects of list management in more detail: List assignment(pg. 23). Making lists(pg. 23). Manipulating list items(pg. 24). Sorting lists(pg. 24). Searching Lists(pg. 24). Informational list primitives(pg. 24). {button See Also, ALink(crunch,,,)} List assignment Assignment may be used to copy one list to another, or to clear out a list (thus freeing its internally allocated storage).
The make_list primitive is similar to quote_list() but each argument is evaluated in turn. For example: list qlst. mlst; qlst = quote_list(1, qlst); mlst = make_list(1, qlst); In this example, the list qlst will contain two elements -- the number '1', and the string 'qlst'. Remember that none of the arguments are evaluated. Care needs to be taken with this primitive to avoid confusion.
Primitive Description bookmark_list List of bookmarks (placeholders). command_list List of primitives built into CRiSP. dict_list List of all symbols defined in a dictionary. file_glob List of files matching a wild card pattern. key_list Get keyboard bindings. list_of_bitmaps List of all bitmaps and pixmaps in a .xpl file. list_of_buffers List of all buffer IDs. list_of_dictionaries List of all object dictionaries.. list_of_keystroke_macros List of all defined keystroke macros.
→ Function definitions(pg. 27). → Expressions(pg. 27). → Loop constructs(pg. 28). → Conditional test - if(pg. 29). → Selection: switch(pg. 29). {button See Also, Alink(crunch,,,)} Declarations There are two main types of declarations -- function definitions and data declarations. A function definition defines the body of a function. A data declaration is used to declare global variables or specify prototypes.
list l = { "Item-1", {1, 2, 3}, "Item-2", "hello mum", "Item-3", 3.14159, /* Trailing comma optional */ }; {button See Also, ALink(crunch,,,)} Function definitions A function definition has the form: [storage_class_specifier] [type_specifier] function_name ( [arg_list] ) { function_body } The storage_class_specifier is currently ignored, although a future version of the language will be able to understand the static class specifier. The type_specifier is used to indicate the return type of the function.
binary | l -> r binary && l -> r binary || l -> r ternary ?: r -> l binary = += -= *= /= %= >>= <<= &= ^= |= r -> l binary , l -> r -------------------------------------------------------------From K&R, p 49 In the above table, the following are not supported: ->, . (dot), (type), sizeof. Also, crunch does not support structures, unions, pointers, or explicit dereferencing. Crunch supports a fair amount of automatic type co-ercion.
The init-expr is evaluated first. Next the while-expr is evaluated, and if it evaluates to TRUE, then statement is executed. After statement is executed, post-expr is executed. The loop continues until while-expr evaluates to FALSE. Any combination of the init-expr, while-expr, and post-expr may be omitted, as in standard C. If while-expr is omitted, then the loop will execute indefinitely.
case 1: case 2: do_something(); break; case 3: case 4: do_something_else(); break; } The statement-list associated with a case statement may consist of zero or more statements, and may optionally be enclosed in braces, e.g. to allow declaration of local variables: switch (expr) { case 1: { int i; i = 3 * 4; break; } ... } The break statement may be used to terminate the switch statement. The switch statement has a bug associated with it.
messages on . This function is only really useful if you are using a GUI version of CRiSP, since otherwise the printf() output will destroy your screen and make it difficult to read the output. The printf() function is useful for tracing a macro's execution, by sprinkling printf() functions within your macro. message() and error() These primitives are similar to printf() but write their output to the status line of the current window.
:/home/fox/bin:/usr/openwin/bin:/usr/openwin/demo:/usr/local/crisp/bin. sun4:/develop/sun4/bin:/develop/scripts:/develop/scripts:/develop/scrip ts/init.d:/develop/scripts/lmfdbase:/develop/scripts/logclient:/develop /scripts/logger:/develop/scripts/newsbase:/develop/scripts/ticker1 TERM=xterm End of Environment *** DEBUG ON (0x0001) *** 04:......... iACC=0 03:........ iACC=0 iACC=0 Returning to macro: exec_macro *** TRIGGER=REG_KEYBOARD *** 01:......(status_update 9 ) Execute macro: status_update 02:.......
switch is at the end of the command Debug buffering Output written to the crisp.log file is normally performed using buffered I/O. Sometimes it may be necessary to cause CRiSP to flush the output buffer as soon as any data is written to the file. This is most normally needed when CRiSP is core dumping and the last buffer has not made it to the disk file. You can cause output flushing to occur by specifying a -1 parameter to the debug primitive.
files which many other editors or standard utilities cannot cope with. Buffer Attributes Each buffer has a number of attributes or modes associated with it. The following is a summary of these attributes, and the following sections explains the purpose of these attributes in further detail. → → → → → → → → → → → → → → → → Ansi mode(pg. 34). Backup flag(pg. 34). Binary flag(pg. 34). Buffer contents(pg. 35). Buffer name, buffer ID and Filename(pg. 35). Carriage-return flag(pg. 35). Character maps(pg. 37).
these files, CRiSP breaks up binary files into lines containing only 32 characters. To avoid problems if the file is modified and written away, CRiSP sets the binary flag. This flag means that the newline character normally written at the end of each line is not saved for binary files, and therefore the edited binary is what the user expects. If this flag were not set or if the user macro turns it off, then newline characters would appear at 32 character intervals in the output file.
frequently annoying problem with vi(1)). The user can clear the read-only bit for a buffer by calling the make_writable macro (available from the features menu) or by typing . Process Buffers Each buffer can have an external system process associated with it. These output from these process is automatically inserted into the buffer as it appears. Input from the keyboard can be directed to these processes. These process buffers are normally use to access the command line interpreter, e.g.
All undo information is undoable itself. This is termed redo. Character Maps A character map is a way of viewing data through a window. Character maps are used to implement the 'view' and 'literal' macros. A character map is simply an array of strings corresponding to each of the possible 256 byte values. When a particular byte is to be displayed in a window, the corresponding string is displayed. For example, when the hexadecimal character 0x41 is to be displayed, the letter 'A' appears on the window.
associated with it. When they are displayed in a window the character map associated with the window is used to view the buffer. (Windows always have a character map associated with them). If a buffer has a character map associated with it (via set_buffer_cmap()), then this is used to override the window definition.
timer(pg. 45). CriSP supports callbacks based on an elapsed real-time clock. window(pg. 33). A window is a character mode window with a view on to a buffer. A single screen can contain multiple character mode windows. →Buffers(pg. 33). →Macros(pg. 41). File Types -- Text files and Binary Files CRiSP allows any file type to be edited, whether the file is binary or text. Editing binary files is allowed although CRiSP does not contain any special facilities (yet) to perform editing on these files.
Autosaving is a feature enabled by default, whereby any modified files (buffers) within the current editing session are saved at 60 second intervals when there is no keyboard activity. This ensures that if you walk away from an editing session and the system crashes, that a copy of your work will be saved. The autosaved file is given a different name to the real file name to avoid prematurely committing changes to the file. These autosaved files are automatically deleted when the user exits from CRiSP.
Key Description Drops a line marker. When a cut or copy command is issued, whole lines will be affected in the operation. Drops a column marker. Text falling within a rectangular region from where the anchor was dropped to the current cursor will be highlighted. Drops an inclusive marker. When a cut or copy command is issued, the character under the cursor will be included in the operation. Drops a non-inclusive marker.
Static macros are very useful, as they are in the C language, to hide private macros in a large macro so that name conflicts do not occur either with the supplied macros or anything else which has no reason to know the names of these private macros. Static macros should be used wherever possible to avoid name conflicts which can cause CRiSP to hang or crash by accidentally replacing an internal macro.
An arbitrary number of macros may be registered for the same event. If more than one macro is registered for the same event, then the macros are called in the order they were registered. Registered macros are convenient short-hand ways of intercepting certain operations within CRiSP. Type Description 0 (REG_TYPED) This macro is called every time a character is inserted into a buffer via (self_insert). 1 (REG_EDIT) This macro is called whenever (edit_file) is called.
new file. 17 (REG_FILE_MOD) This is the modified file trigger. It is called when Crisp detects that the corresponding file on disk for a buffer has been modified. This is used to detect situations where Crisp hasn't completely read in a file but maybe another editing session has destroyed the file. The calling macro should return an integer value to indicate whether the buffer should continue to be edited, or truncated at the current load point. A value of zero means to stop further editing.
undoing back to the point where the buffer no longer needs saving. You should call the inq_modified() primitive to determine which of the two states you are in. 37 (REG_DEFAULT_FILE). This callback is identical to REG_NEW but is called after REG_NEW and only if the input file does not have an extension. This allows a macro to set up things like colorization type to be written based on the contents of the file, if it cannot be determined from the file extension 38 (REG_CHANGE_DIRECTORY).
Note that this timer mechanism is independent of the idle timer mechanism described elsewhere. The idle timer mechanism is specifically designed to support the autosave functionality. In theory the autosave mechanism could be built from the timer functionality since it is more generic (although it would be tricky to build an autosave mechanism based on the number of keystrokes typed, which the autosave mechanism does support).
15 COL_BG_STRINGS Background color for string literals. 16 COL_FG_KEYWORDS Foreground color for language keywords. 17 COL_BG_KEYWORDS Background color for language keywords. 18 COL_FG_MODIFIED Foreground color for modified lines. 19 COL_BG_MODIFIED Background color for modified lines. 20 COL_FG_HASH Foreground color for directives. 21 COL_BG_HASH Background color for directives. 22 COL_LINE_NOS Foreground color for line numbers.
<, %, ^ matches the beginning of a line. >, $ matches the end of a line. ? matches any single character. * matches zero or more characters [..] matches any character within the [..] \c used to set the cursor after a match. \n Matches the newline character at the end of a line. \< Match beginning of line or non-word character. \> Match end of line or non-word character. Two regular expressions juxtaposed allow concatenation.
For example, the following expression: cat*dog matches any line which contains the word cat followed by somewhere else on the line, the word dog. Character Class: [..] and .. The square bracket operators are used to match one or more characters from a class of characters. If the expression is of the form '[..]' then a match is successful if the character being matched is any of the characters within the square brackets.
[A-Za-z]]+ matches the final word in a sentence. The '.' matches the full-stop after it. The expression [ ]@ matches zero or more spaces which may separate the full-stop and the first letter of the next sentence. Regular Expression Grouping: .. The regular expression grouping characters are used for one of two purposes - alter the precedence in which the regular expression is parsed, and to define groupings of regular expressions for use by the translation mechanism.
backward matching. The search macros - search_fwd, search_back, translate, search_string and search_list have a parameter, labelled 're' which is used to control the minimal/maximal matching. The minimal/maximal terminology refers to the way that the closure operators (i.e. zero or more or one or more sequences of regular expressions) are matched. This parameter can have one of seven valid values: -3, -2, -1, 0, 1, 2, 3.
functionality because this can help to increase performance whilst keeping the macro interface fairly simple. One of the design goals of the macro facilities is that macros should be as portable as possible, i.e. the intricacies and idiosyncrasies of particular GUI toolkits are hidden. This means it is easier to program the macros, but at the risk of losing absolute functionality. Some aspects of the GUI objects expose the underlying toolkits but only in a manner which is portable.
years, such organisations as Microsoft, IBM, and the OSF have strived to achieve the ultimate user interface. None of these organisations has produced a finished product, in the sense that no matter what they do, there are always more tweaks and improvements which can be made. Dialog boxes and the objects contained within them are fairly abstract.
creating a dialog box. 1. Firstly, we sketch or conjure up a mental model of what the dialog box is going to look like. E.g. we consider the user interface components, such as input fields, toggles, push buttons. Most dialog boxes have a common core of functionality, such as an OK and CANCEL button. Stylistics issues dictate that these are normally at the bottom or right hand side of a dialog box. 2. Next we look at each user interface object and decide what its purpose is, how it responds to user input.
it. At various times you need to refer to the individual objects within the dialog box, e.g. so that you can retrieve the current status of the object, change an attribute value, or decide in the callback code, which object has just been actioned on by the user. In order to do this, you need to give an object a name (via the DBOX_NAME attribute). It is not mandatory that you do give an object a name, but you will not be able to refer to the object without one.
.... object-2 attributes for object-2 .... .... object-n attributes for object-n .... You will notice in the supplied macros that indentation is used to show this implied nesting structure.
oriented implementation. DBOX_DIRECTORY An list type object which contains semantics for implementing a selection from a set of valid files or directories. DBOX_DISPLAY This object type is never explicitly created in a create_object() definition, but is used to refer to the physical screen. For example, using this object type it is possible to inquire about the physical screen size. DBOX_DRIVE (Windows only).
DBOX_PANED_WINDOW A container object used to contain two child objects. The real-estate allocated to the children can be changed by using a slider located between the windows. Used in CRiSP to implement the contents window. DBOX_RTF An object which understand the RTF (Rich Text Format) text format and is used as the basis of the hypertext help system. DBOX_RULER Ruler which is associated with a CRiSP edit window. DBOX_SCREEN A screen object corresponds to a CRiSP character mode editing screen.
DBOX_TREE A tree-like widget which supports outlining views of data. A tree widget is a bit like a DBOX_LIST widget but you can control the visibility of hierarchies of the data. DBOX_VSCROLLBAR Obsolete. DBOX_HSCROLLBAR Obsolete. Some of the object types described above are not fully implemented. They may be in future versions, but there is no guarantee of this. For a long period of time, CRiSP has evolved internally to create the object structure described in this manual.
DBOX_CENTERED, DBOX_BUTTON, " Apply ", DBOX_NEXT_COLUMN, TRUE, DBOX_CENTERED, DBOX_BUTTON, " Help ", DBOX_NEXT_COLUMN, TRUE, DBOX_CENTERED, DBOX_BUTTON, " Cancel ", DBOX_NEXT_COLUMN, TRUE, DBOX_CENTERED )); These very basic layout semantics are now sufficient to describe most types of dialog boxes, but there is still a long way to go. One of the next issues to resolve is what happens when a dialog box is resized? Many dialog boxes are fairly static in nature, and having them resizable is of little benefit.
When laying out a dialog box, CRiSP tries hard to avoid objects from overlapping, so it is normally safe to use the DBOX_ANCHOR attributes even if there are objects to the left, right, top or bottom of the specified object. With what has been described so far, it is possible to describe fairly abstract dialog boxes where we do not care too much about the fine level of detail in a dialog box, and thus we can be reasonably user and environment independent.
/* The first object is an input field, */ /* and we have a label to the left of the */ /* input field. */ DBOX_FIELD, "Please type in: ", /* The input field is marked as stretchable */ DBOX_ALLOW_RESIZE, TRUE, /* Constrain the left side of the */ /* input field to be in the position as */ /* the left side of the object called */ /* "list" */ DBOX_ATTACH_LEFT_TO_LEFT, "list", /* Do the same for the right side */ DBOX_ATTACH_RIGHT_TO_RIGHT, "list", /* Create a scrolling list widget with 3 lines in it.
as children of a DBOX_TOOL_BAR. For the DBOX_MENU_BAR case, only DBOX_MENU_BUTTON or DBOX_DROP_SITE types are reasonable children. For DBOX_TOOL_BAR, only DBOX_TOOL_BUTTONs are valid. For the DBOX_STATUS_BAR, DBOX_STATUS_PANEL are the sub-objects which can be used. In the case of the menu bar, it is necessary to define the hierarchy of sub-menus and cascaded menus which can be created, along with any attributes each of the sub-objects may require.
dialog box. There is a solution to this, and it is called object-grouping. Object-grouping is a mechanism where you create a collection of objects as if they were a single object. More precisely, you create a bounding rectangle which encompasses the sub-objects, and you use the existing layout attributes to lay out the container object.
group is very similar to a normal group, but was designed to solve a different problem, and first came to life with the implementation of the DBOX_STATUS_BAR attribute. As described previously, the menu bar, tool bar, and status bars are all similar in that they are actually a collection of appropriate sub-objects. The grouping mechanism is used for the status bars, tool bars, and menu bars as a way of associating the individual components with the parent object.
every time you click that button, the number is incremented. Where do you store the current value of the label? (You can use the label itself, but this is a special case, and doing so fails to illustrate the point being made here). You can use a global variable, e.g.
CRiSP takes a Microsoft Windows style approach. CRiSP is an interpreter and the macro language can best be considered as a very powerful language for configuring CRiSP. It is not necessarily designed to incorporate all the latest and greatest ideas in programming methodology, and hence takes poetic license to implement the most reasonable and easiest approach to the problems it wants to solve. Macros in general are very high level programming statements.
This is a piece of CRiSP macro code. The CRiSP macro code looks and feels a lot like C. Without necessarily knowing any of the details of the macro language, you can immediately see that different parts of the edit window are colored differently. In the sample, comments have a grey background with black text. These comments act as eye-catchers, and nicely sub-divide long code sequences into regions of interest.
definition is needed to tell CRiSP how to perform colorization of keywords for files of a particular type. CRiSP comes with a variety of supported languages, but you can use this dialog to create your own or to modify a supplied definition. For example, you might be programming in C and want to add custom function libraries so that they are colored in a different color.
New Clears the dialog in preparation for typing in a new definition. You are prompted to save any changes before the dialog box is cleared out. Save Saves the current definition and closes the dialog box. Add Appends the current keyword along with the flags and type fields to the keyword table. Remove Deletes the currently selected word in the table. .KWD Keyword File Format Colorization:.kwd file formatCRiSP stores colorizer or keyword descriptions in a special file, called a .KWD file.
colorizers available, based on the filename not the section name. The flags= Directive Colorization:flags directiveThe flags= entry in a keyword section are used to provide various hints about the language being colorized. Each hint is a word; see the list below for a description of the various attributes defined. There can be multiple flags= lines. Use whatever layout best suits you. The various keywords described for the flags= directive may also be specified with the actual keyword definitions as well.
spell_text For most languages, you would not spell check all the types of entities in your files. You would normally restrict spell checking to things such as comments or quoted literal strings. For those types of languages you explicitly state (using the spell keyword) that each syntactic item needs spell checking. In the case of a language like HTML, you would want to check the raw text but not check any specific keyword definition; this is almost the direct opposite of other programming language files.
Defines the characters which can form the 2nd and subsequent characters in a keyword or variable name. This may be different from the char_start field. For example in C, this is the same as the first character, but also includes the digits: [A-Za-z0-9_]. char_last Specify this to indicate characters which are a valid part of a keyword or variable name. Whereas char_start and char_next specify characters which form part of the name, char_last also specifies that any of these characters terminate the name.
char_backslash= This class is used to redefined the backslash character. In many languages, backslash character is used to turn off (or escape) the meaning of the following character. For example in a shell script or the C language, this mechanism allows you to embed a quote inside a string, which would otherwise normally terminate the string. Whether your language will use backslashes or not is handled by specifying the accept_backslashes keyword prefix, e.g.
→ More than one keyword can be specified on each line; each keyword is enclosed in double quotes. Backslashes are used inside the quotes to escape the next character. (Usually only needed for literal double quotes or backslashes. → Keywords are case dependent unless the case_independent flag is applied to the keyword or specified in the flags= line. → Each keyword can be preceded by one or more flags. The keyword specific flags are described below.
Keyword Regular Expressions Colorization:keyword regular expressionsKeyword regular expressions are a way of allowing generic styles of strings to be specified as keywords or string constants, etc. In a language such as C, it is obvious that something like "case" specifies a keyword, but it is more difficult to describe a string literal because although the start and end of the literal are well defined, anything can occur inside the quote marks delimiting the string.
inside the string, or any other non-printable character, you can use a backslash to affect the following characters. In many languages, string constants are handled differently. In ADA, strings are enclosed in single quotes, and to quote a single quote, you just specify three apostrophes in a row. There are other coding differences from one language to another. CRiSP has evolved to cater for many of these different styles, but it is not generic enough to allow any kind of quoting policy.
operator= operator= operator= operator= "+=" "-=" "*=" "/=" "|=" "&=" "^=" "==" "!=" "<<=" ">>=" "+" "-" "*" "/" "^" "&" "|" "!" "~" "?" ":" "++" "--" "(" ")" "[" "]" ">" ">=" "<" "<=" "->" ">>" "<<=" /****************************************************************/ /* C keywords.
keyword="union" keyword="while" "write" Interprocess Communication and CRiSP Interprocess communication is the means to allow other programs to communicate with CRiSP, or vice versa. IPC communication is a very powerful mechanism for extending an existing application or CRiSP. For example, CRiSP provides IPC communication when dealing with shell buffers, compilation commands and filtering.
support these pipes. Windows/32 named pipes are more like TCP connection which allow two tasks on different machines to communicate. PTYs(pg. 84). A PTY, or pseudo-teletype, is the mechanism used by terminal emulators under Unix and X-Windows, to allow the user to have separate xterm windows. Some programs can be communicated to via pty's more easily than using any other IPC mechanism. For example, the vi editor under Unix has no IPC support in it.
The key to writing non-blocking macros is to write them based on callbacks, using the ipc_register() function. There are four conditions for which you can register a callback: IPC_TRIGGER_READIPC_TRIGGER_READ indicates data is a available to be read. You can successfully call ipc_read() once to read data. If you attempt to call ipc_read() more than once within a callback you may block if the no data is available. If you back a zero length string then the connection has been disconnected by the remote end.
Client Side Programming Issues When using TCP to connect to a remote site, there may be some considerable delay in the connection being accepted, or the remote site may be down, in which case you can hang CRiSP until the connection request completes or the connection times out. You can avoid this problem by OR-ing the IPC_NON_BLOCKING flag into the IPC_TCP connection type.
/* /* /* /* if We have either successfully or unsuccessfully */ connected to the remote host. */ We can tell the difference by whether the ipc_write */ is successful or not. */ (ipc_write(ipc_id, "Hello\n") < 0) { message("Writing data failed."); } /* If we keep the connection open at this point, make */ /* sure to unregister the IPC_TRIGGER_WRITE trigger */ /* otherwise it will keep firing. */ /* In this example, we simply close the connection when */ /* we are done.
Pipe Communications There are two forms of pipes which can be used: anonymous pipes and named pipes. Both types are very similarly - the difference is in the naming conventions used by the client and server to connect to each other. Presently, these two forms of communication are only implemented under Unix.PipesIPC_ANON_PIPEIPC_NAMED_PIPE In order to use pipes, you need to execute some other process with its stdin and stdout set to a pair of file descriptors which are used by CRiSP to communicate with.
zero bytes, then the other end of the pipe has most likely terminated. Alternatively you may use the ipc_register() callback to register notification on the death of a process. {button See Also, ALink(ipc,,,)} DDE Communications DDE is a special type of IPC available only on the Windows platform. DDE is a simple programming language based IPC mechanism, meaning that to implement all aspects of DDE requires low level access to a programming language such as C, or C++.
Client Side operation To make a client request, you need to create an IPC channel and specify the name of the service and topic you wish to connect to. For example to connect to a WEB browser, you would use something like this: int ipc_id; ipc_id = ipc_create(IPC_DDE, "NETSCAPE:WWW_OpenURL"); if (ipc_id >= 0) { ipc_write(ipc_id, "http://www.crisp.com/"); } If the specified service is not available then the ipc_create function will fail.
mechanism.SignalsSIGUSR1SIGUSR2register_macroREG_SIGNALasync.cr Signal based communication The SIGUSR1 and SIGUSR2 IPC mechanism is probably the simplest to use and most primitive way to cause CRiSP to perform an action on demand. In order to make use of this signal, you need to write a macro which will be invoked when either of these signals is invoked. (CRiSP treats both signals as identical - you cannot distinguish them from within a macro).
keyboard. When you press a key, CRiSP looks at the current buffer and looks to see if a local keyboard has been defined for this buffer. If so, it checks the local keyboard to determine if the current key stroke has a macro binding. If one is found then the associated macro is invoked. If the local keyboard isn't defined, or if the local keyboard does not contain a binding for the current keystroke, then CRiSP looks at the global keyboard.
Scan Codes As described above, CRiSP uses a set of key definitions which allow you to create macros which are not dependent on the keyboard and system you are using. You do this by using key names such as . These key names are translated into key codes. Some keys on the keyboard, notably the keypad and cursor keys are duplicates. (Technically they are not duplicates; whether they are duplicates or not depends on the application or keyboard bindings you have in effect).
This populates the current keyboard with all the normal typeable characters (A..Z, a..z, 0..9, etc) so that they are self-inserting (see self_insert). keyboard_reset Clears out all key bindings from the current keyboard. Keyboard binding files CRiSP provides a facility for storing keyboard bindings in a file separate from a macro. The CRiSP distribution comes with variety of editor emulations, which are stored in these files. (See etc/*.kbd in the distribution).
files are compiled directly into loadable files with a .cm extension). CRiSP can load .m files directly without any need for compilation, but this can be slower than loading an equivalent compiled file so this facility is rarely used or needed. The .m source files are compiled with the cm program. *** NOTE *** The name 'cm' conflicts with the calendar manager utility which is available under SunOS 4.x and Solaris 2.x when using OpenLOOK.
Page 92