home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-09-27 | 34.9 KB | 1,112 lines |
- # $Header: P:/source/ppee/macros/electric.pev 1.65 24 Sep 1990 17:35:08 skipr $
-
- ##############################################################################
- #
- # Sage Software - POLYTRON Division
- # 1700 NW 167th Place
- # Beaverton, OR 97006
- #
- # Copyright 1990, Sage Software, Inc.
- #
- # Permission is hereby granted for licensed users of Sage Professional
- # Editor and PolyAwk to copy and modify this source code for their own
- # personal use. These derivative works may be distributed only to other
- # licensed Sage Professional Editor and PolyAwk users. All other usage
- # is prohibited without express written permission from Sage Software.
- #
- ##############################################################################
-
- #### $Workfile: electric.pel $: helper routines for entering C code
- #
- # There are three principal facilities in this package:
- # 1. Insertion of code templates
- # (see "function initialized_template()" in this module
- # on how to add new templates)
- # 2. Bracket matching (several flavors)
- # 3. Auto-indentation
- #
-
- #
- # Clipper Support and general improvements made to this module
- # have be provided by P. Polakoff III, 3P Software, Inc.
- #
-
- ### "electric" templates program-entry features.
- #
- # The template entry facility works differently than some other
- # products' in that templates are inserted only upon demand, and
- # not automatically upon recognition of an abbreviation.
- #
- # Templates are auto-indented independently of the autoindent mode.
- #
- # Template insertion is activated manually by a keypress. The
- # definition of ESCAPE may be freely changed from the ESC key to
- # SPACE or any other key.
- #
- # The mode may be turned on and off by calls to ec() or
- # toggle_electric(). It additionally is enabled or disabled depending
- # on whether the extension on the current buffer's name matches one of
- # the patterns in the expand template list.
- #
- # Internally the mode is turned on, so it is sufficient for keymaps
- # merely to bind the associated functions to keys.
- #
- # Multiple-character abbreviation sequences are allowed.
- #
- # Bug: mark_matching() highlights only the first char of the
- # destination of multi-char brackets. It should highlight the entire
- # keyword (or optionally only the enclosed text).
- #
- # This eventually needs to be generalized so that different extensions
- # cause different templates to be enabled.
- #
- # We probably should default electric and auto-indent modes to ON.
- #
-
- global language_template # the map of abbreviations onto expanded strings
- global electric_extensions = "" # current language template entensions
- global file_extensions
- global extensions_initialized = 0;
-
- global D_DIALECT = "clipper87" # dBASE dialect (used by errorfix.pel also)
- global ELEC_LANG = "text" # current electric language
-
- global electric_mode = 0 # 0 = disabled, 1 = enabled
- local initialized_file_ext; # specifies the last extension used when
- # initialized_template() was called.
- local newEditFileId;
-
-
- #
- # Addition of new templates:
- # --------------------------
- # Add a new element to the file_extensions[] array and initialize it
- # with the associated extensions as demonstrated below. Then add
- # the new electric array as defined in initialize_template() below.
- #
-
- # Possible file extents for each language. Each is a regular expression
- # to match the buffer's filename extension.
- #
- # "electric_extensions" takes on one of these values initialized in
- # initialize_extensions().
- #
-
- function initialize_extensions() {
- delete(file_extensions)
- file_extensions["text"]="\\.txt$|\\.doc$"
- file_extensions["c"] = "\\.c$|\\.h$|\\.awk$|\\.cpp$|\\.pel$"
- file_extensions["dbase"]= "\\.prg$|\\.gen$|\\.cod$|\\.gtl$|\\.tlb$|\\.tem$"
- file_extensions["clipper87"]="\\.prg$|\\.pre$|\\.gen$|\\.cod$|\\.gtl$|\\.tlb$|\\.tem$"
- file_extensions["clipper50"]="\\.prg$|\\.ch$|\\.ppo$|\\.gen$|\\.cod$|\\.gtl$|\\.tlb$|\\.tem$"
- file_extensions["force"]="\\.prg$|\\.hdr$"
- file_extensions["pascal"]= "\\.pas$"
- file_extensions["basic"]= "\\.bas$"
- file_extensions["asm"]= "\\.asm$|\\.mac$|\\.inc$"
- extensions_initialized = 1;
- }
-
-
-
- ## ec()
- #
- # enable/display template generation ( 0 = disable, 1 = enable );
- #
- function ec( mode ){
- if (argcount())
- toggle_electric( mode );
- else
- toggle_electric()
- }
-
- ## toggle_electric()
- #
- # enable/display template generation ( 0 = disable, 1 = enable );
- #
- function toggle_electric( selection ){
- local verbose = 0
-
- if( argcount() < 1 ){
- selection = !electric_mode
- verbose = 1
- }
-
- electric_mode = selection
-
-
- if (electric_mode) {
- if (!newEditFileId) {
- newEditFileId = function_id( "electric_edit_file" );
- attach_event_handler( EVENT_NEW_EDIT_FILE, newEditFileId );
- }
- electric_edit_file();
- } else {
- if (newEditFileId) {
- delete_event( EVENT_NEW_EDIT_FILE, newEditFileId );
- newEditFileId = 0;
- }
- }
-
-
- if( verbose )
- message( electric_mode \
- ? "Electric-C enabled" \
- : "Electric-C disabled" )
- }
-
- ## initialize_template()
- #
- # Initialize the correct template for the language being used.
- # The language is determined by the extension of the current buffer's
- # name. If the template has already been initialized, it is ignored.
- #
- # Addition of new templates:
- # --------------------------
- # To add a new template, create a new element in the file_extensions
- # array defined in initialize_extensions() above.
- #
- # Next, duplicate one of the if-else statements below and change the
- # language_template[] settings appropriately. Also, be sure the comparison
- # with "_extensions" (your new variable name) is updated as well.
- #
- local function initialize_template(){
-
-
- if ( path_ext(buffer_name) == initialized_file_ext )
- return;
- else
- initialized_file_ext = path_ext( buffer_name );
-
- if ( !extensions_initialized )
- initialize_extensions();
-
- if ( buffer_name ~ file_extensions["c"] ){
- ## Microsoft C5.1 compatible templates
-
- if ( electric_extensions == file_extensions["c"] )
- return;
-
- delete( language_template ); # delete last template and start over
- electric_extensions = file_extensions["c"]
-
-
- language_template[ "{" ] = "{\n\t@\n}" # }
- language_template[ "(" ] = "( @ )"
- language_template[ "[" ] = "[ @ ]"
- language_template[ "/" ] = "/* @ */"
- language_template[ "*" ] = "/*\n** @\n*/"
- language_template[ "#i" ] = "#include <@>"
- language_template[ "#d" ] = "#define @"
- language_template[ "#p" ] = "#pragma @"
- language_template[ "#u" ] = "#undef @"
- language_template[ "ac" ] = "access(\"@\",);"
- language_template[ "ca" ] = "case @: "
- language_template[ "cl" ] = "close(@);"
- language_template[ "do" ] = "do {\n\t@\n} while();"
- language_template[ "if" ] = "if(@){\n\t\n}"
- language_template[ "ie" ] = "if(@){\n\t\n} else {\n\t\n}"
- language_template[ "el" ] = "else {\n\t@\n}"
- language_template[ "fo" ] = "for(@;;){\n\t\n}"
- language_template[ "fs" ] = "fscanf(@,\"\");"
- language_template[ "fp" ] = "fprintf(@,\"\",);"
- language_template[ "fr" ] = "fread(@,,);"
- language_template[ "ft" ] = "ftell(@);"
- language_template[ "fw" ] = "fwrite(@,,);"
- language_template[ "gc" ] = "getc(@);"
- language_template[ "gh" ] = "getchar();"
- language_template[ "gs" ] = "gets(@);"
- language_template[ "gw" ] = "getw(@);"
- language_template[ "wh" ] = "while(@){\n\t\n}"
- language_template[ "sw" ] = "switch(@){\n\tcase : \ndefault: \n\b}"
- language_template[ "ts" ] = "typedef struct @ {\n \n}"
- language_template[ "ty" ] = "typedef @"
- language_template[ "pc" ] = "putc(@,);"
- language_template[ "ph" ] = "putchar(@);"
- language_template[ "pr" ] = "printf(\"@\",);"
- language_template[ "ps" ] = "puts(\"@\");"
- language_template[ "pw" ] = "putw(@,);"
- language_template[ "sc" ] = "scanf(@,\"\",);"
- language_template[ "ss" ] = "sscanf(@,\"\",);"
- language_template[ "sp" ] = "sprintf(@,\"\",);"
- language_template[ "fu" ] = "function @ (){\n \n}"
- language_template[ "vf" ] = "vfprintf(@,\"\",);"
- language_template[ "vp" ] = "vprintf(\"@\",);"
- language_template[ "vs" ] = "vsprintf(@,\"\",);"
- language_template[ "op" ] = "open(\"@\",,);"
- language_template[ "re" ] = "read(@,,);"
- language_template[ "rn" ] = "rename(\"@\",\"\");"
- language_template[ "wr" ] = "write(@,,);"
- language_template[ "ls" ] = "lseek(@,,SEEK_);"
- language_template[ "_s" ] = "_splitpath(@,,,,);"
- language_template[ "_m" ] = "_makepath(@,,,,);"
- language_template[ "un" ] = "unlink(\"@\");"
- language_template[ "ma" ] = "malloc(@);"
- language_template[ "fe" ] = "free(@);"
- language_template[ "st" ] = "static @;"
-
- } else if ( (buffer_name ~ file_extensions["dbase"]) \
- || (buffer_name ~ file_extensions["clipper87"]) \
- || (buffer_name ~ file_extensions["clipper50"]) \
- || (buffer_name ~ file_extensions["force"]) ){
-
- if( (electric_extensions == file_extensions["dbase"]) \
- || (electric_extensions == file_extensions["clipper87"]) \
- || (electric_extensions == file_extensions["clipper50"]) \
- || (electric_extensions == file_extensions["force"]) )
- return;
-
- delete(language_template); # delete last template and start over
- dBaseDialect()
- electric_extensions = file_extensions[ELEC_LANG]
- if ( ELEC_LANG == "clipper87" ) {
- language_template[ "(" ] = "(@)"
- language_template[ "[" ] = "[@]"
- language_template[ "*" ] = "***\n*** @\n***"
- language_template[ "&" ] = "\t\t&& @"
- language_template[ "#i" ] = "#include @"
- language_template[ "#d" ] = "#define @"
- language_template[ "ii" ] = "iif((@),,)"
- language_template[ "if" ] = "if(@)\n\t\nendif"
- language_template[ "ie" ] = "if(@)\n\t\nelse\n\t\nendif"
- language_template[ "fo" ] = "for @\n\t\nnext"
- language_template[ "ca" ] = "do case\n\tcase @\n\t\notherwise\n\t\n\b\bendcase"
- language_template[ "el" ] = "else\n\t@"
- language_template[ "ef" ] = "elseif(@)\n\t"
- language_template[ "en" ] = "endif"
- language_template[ "wh" ] = "do while (@)\n\t\nenddo"
- language_template[ "do" ] = "do @ with "
- language_template[ "be" ] = "begin sequence\n\t@\nend"
- language_template[ "pr" ] = "procedure @\nparameters\n\t\nreturn"
- language_template[ "fu" ] = "function @\nparameters\n\t\nreturn('')"
- language_template[ "le" ] = "len(@)"
- language_template[ "tr" ] = "trim(@)"
- language_template[ "us" ] = "use @ "
- language_template[ "in" ] = "index @"
- language_template[ "al" ] = "alias @"
- language_template[ "cl" ] = "clear @"
- language_template[ "co" ] = "copy to @ fields for while "
- language_template[ "pv" ] = "private @"
- language_template[ "gt" ] = "go top"
- language_template[ "gb" ] = "go bottom"
- language_template[ "pu" ] = "public @"
- language_template[ "de" ] = "delete @ for while "
- language_template[ "se" ] = "select @"
- language_template[ "as" ] = "asc(@)"
- language_template[ "ch" ] = "chr(@)"
- language_template[ "at" ] = "at(@,)"
- language_template[ "ct" ] = "ctod(@)"
- language_template[ "dc" ] = "dtoc(@)"
- language_template[ "cm" ] = "cmonth(@)"
- language_template[ "dt" ] = "date()"
- language_template[ "da" ] = "day(@)"
- language_template[ "bf" ] = "bof()"
- language_template[ "ef" ] = "eof()"
- language_template[ "ds" ] = "dtos(@)"
- language_template[ "lo" ] = "lower(@)"
- language_template[ "up" ] = "upper(@)"
- language_template[ "mi" ] = "min(@,)"
- language_template[ "ma" ] = "max(@,)"
- language_template[ "mo" ] = "month(@)"
- language_template[ "yr" ] = "year(@)"
- language_template[ "pc" ] = "pcount() = @"
- language_template[ "ra" ] = "rat(@,)"
- language_template[ "ss" ] = "save screen to @"
- language_template[ "rs" ] = "restore screen from @"
- language_template[ "tf" ] = "transform(@,)"
- language_template[ "su" ] = "substr(@,,)"
- language_template[ "sp" ] = "space(@)"
- language_template[ "re" ] = "replicate(@,)"
- language_template[ "rp" ] = "replace @"
- language_template[ "va" ] = "val(@)"
- language_template[ "pi" ] = "picture @"
- language_template[ "vl" ] = "valid(@)"
- } else if ( ELEC_LANG == "clipper50" ) {
- language_template[ "{" ] = "{@}"
- language_template[ "(" ] = "(@)"
- language_template[ "[" ] = "[@]"
- language_template[ "*" ] = "/*\n** @\n*/"
- language_template[ "/" ] = "// @"
- language_template[ "&" ] = "\t\t// @"
- language_template[ "@" ] = "DevPos(@,)"
- language_template[ "?" ] = "QOut(@)"
- language_template[ "??" ] = "QQOut(@)"
- language_template[ "#i" ] = "#include \"@\""
- language_template[ "#d" ] = "#define @"
- language_template[ "#c" ] = "#command @\t=>\t"
- language_template[ "#t" ] = "#translate @\t=>\t"
- language_template[ "ar" ] = "Array(@)"
- language_template[ "ii" ] = "iif((@),,)"
- language_template[ "if" ] = "if(@)\n\t\nend"
- language_template[ "ie" ] = "if(@)\n\t\nelse\n\t\nend"
- language_template[ "fo" ] = "for @:= to \n\t\nnext"
- language_template[ "ca" ] = "do case\n\tcase @\n\t\notherwise\n\t\n\b\bend"
- language_template[ "el" ] = "else\n\t@"
- language_template[ "ef" ] = "elseif(@)\n\t"
- language_template[ "en" ] = "end"
- language_template[ "wh" ] = "while(@)\n\t\nend"
- language_template[ "be" ] = "begin sequence\n\t@\nend"
- language_template[ "pr" ] = "procedure @\nparameters\n\t\nreturn"
- language_template[ "fu" ] = "function @( )\n\t\nreturn(NIL)"
- language_template[ "le" ] = "len(@)"
- language_template[ "tr" ] = "trim(@)"
- language_template[ "us" ] = "use @ "
- language_template[ "in" ] = "index @"
- language_template[ "al" ] = "alias()"
- #############################################################################
- # Special Note: The following macro expansions are supplied in two forms.
- # The first form is the form preferred by Nantucket for use with Clipper 5.0
- # The second form is the translation form as performed by the Clipper 5.0
- # preprocessor. It is to the programmer's discretion to choose which of
- # these macro sets to utilize, however it should be noted that the use of
- # the internal form may not be supported in future Clipper releases.
- #############################################################################
- ## Nantucket preferred form
- #language_template[ "cl" ] = "clear"
- #language_template[ "gt" ] = "go top"
- #language_template[ "gb" ] = "go bottom"
- #language_template[ "se" ] = "select @"
- #language_template[ "us" ] = "use @"
- ## Internal form
- language_template[ "cl" ] = "__Clear()"
- language_template[ "gt" ] = "__dbGoTop()"
- language_template[ "gb" ] = "__dbGoBottom()"
- language_template[ "se" ] = "__dbSelect(@)"
- language_template[ "us" ] = "__dbUse(0,NIL,@,,.T.,.F.)"
- #############################################################################
- language_template[ "pv" ] = "private @"
- language_template[ "pu" ] = "public @"
- language_template[ "lc" ] = "local @"
- language_template[ "st" ] = "static @"
- language_template[ "as" ] = "asc(@)"
- language_template[ "ch" ] = "chr(@)"
- language_template[ "at" ] = "at(@,)"
- language_template[ "ct" ] = "ctod(@)"
- language_template[ "dc" ] = "dtoc(@)"
- language_template[ "cm" ] = "cmonth(@)"
- language_template[ "dt" ] = "date()"
- language_template[ "da" ] = "day(@)"
- language_template[ "bf" ] = "bof()"
- language_template[ "ef" ] = "eof()"
- language_template[ "ds" ] = "dtos(@)"
- language_template[ "lo" ] = "lower(@)"
- language_template[ "up" ] = "upper(@)"
- language_template[ "mi" ] = "min(@,)"
- language_template[ "ma" ] = "max(@,)"
- language_template[ "mo" ] = "month(@)"
- language_template[ "yr" ] = "year(@)"
- language_template[ "pc" ] = "pcount()==@"
- language_template[ "ra" ] = "rat(@,)"
- language_template[ "ss" ] = "@:=savescreen(0,0,maxrow(),maxcol())"
- language_template[ "rs" ] = "restscreen(0,0,maxrow(),maxcol(),@)"
- language_template[ "tf" ] = "transform(@,)"
- language_template[ "su" ] = "substr(@,,)"
- language_template[ "sp" ] = "space(@)"
- language_template[ "re" ] = "replicate(@,)"
- language_template[ "rp" ] = "FIELD->@:="
- language_template[ "va" ] = "val(@)"
- language_template[ "vt" ] = "valtype(@)"
- } else if ( ELEC_LANG == "force" ) {
- language_template[ "#i" ] = "#include @"
- language_template[ "#d" ] = "#define @"
- language_template[ "*" ] = "**\n**\t@\n**"
- language_template[ "dd" ] = "DBFDEF @\n\t\nENDDEF"
- language_template[ "vd" ] = "VARDEF\n\t@\nENDDEF"
- language_template[ "id" ] = "INDEXDEF\n\t@\nENDDEF"
- language_template[ "rd" ] = "REPORTDEF @\n\t\nENDDEF"
- language_template[ "ld" ] = "LABELDEF @\n\t\nENDDEF"
- language_template[ "gd" ] = "GROUPDEF\n\t\nENDDEF"
- language_template[ "sg" ] = "SUBGROUPDEF\n\t\nENDDEF"
- language_template[ "cd" ] = "COLUMNDEF\n\t\nENDDEF"
- language_template[ "if" ] = "IF(@)\n\t\nENDIF"
- language_template[ "ie" ] = "IF(@)\n\t\nELSE\n\t\nENDIF"
- language_template[ "ca" ] = "DO CASE\n\tCASE @\n\t\nOTHERWISE\n\t\n\b\bENDCASE"
- language_template[ "el" ] = "ELSE\n\t@"
- language_template[ "en" ] = "ENDIF"
- language_template[ "wh" ] = "DO WHILE (@)\n\t\nENDDO"
- language_template[ "do" ] = "DO @ WITH "
- language_template[ "fu" ] = "FUNCTION @\nPARAMETERS\n\t\nENDPRO"
- language_template[ "pr" ] = "PROCEDURE @\nPARAMETERS\n\t\nENDPRO"
- language_template[ "fm" ] = "FORMAT @\n\tENDPRO"
- language_template[ "ru" ] = "REPEAT\n\t@\nUNTIL"
- language_template[ "le" ] = "len(@)"
- language_template[ "lo" ] = "locate @"
- language_template[ "tr" ] = "trim(@)"
- language_template[ "us" ] = "USE @ "
- language_template[ "in" ] = "INDEX @"
- language_template[ "cl" ] = "CLEAR @"
- language_template[ "co" ] = "COPY TO @"
- language_template[ "gt" ] = "GOTO TOP"
- language_template[ "gb" ] = "GOTO BOTTOM"
- language_template[ "de" ] = "DELETE @"
- language_template[ "se" ] = "SET @"
- language_template[ "as" ] = "asc(@)"
- language_template[ "ch" ] = "chr(@)"
- language_template[ "at" ] = "at(@,)"
- language_template[ "ct" ] = "ctod(@)"
- language_template[ "dc" ] = "dtoc(@)"
- language_template[ "cm" ] = "cmonth(@)"
- language_template[ "da" ] = "day(@)"
- language_template[ "bf" ] = "bof()"
- language_template[ "ef" ] = "eof()"
- language_template[ "lo" ] = "lower(@)"
- language_template[ "up" ] = "upper(@)"
- language_template[ "mo" ] = "month(@)"
- language_template[ "yr" ] = "year(@)"
- language_template[ "ra" ] = "rat(@,)"
- language_template[ "ss" ] = "savescrn(@,,,)"
- language_template[ "rs" ] = "restorescrn(@)"
- language_template[ "su" ] = "substr(@,,)"
- language_template[ "st" ] = "stuff(@)"
- language_template[ "re" ] = "replicate(@,)"
- language_template[ "rp" ] = "replace @"
- language_template[ "va" ] = "val(@)"
- language_template[ "pi" ] = "picture @"
- } else {
- language_template[ "(" ] = "(@)"
- language_template[ "[" ] = "[@]"
- language_template[ "*" ] = "**\n**\t@\n**"
- language_template[ "&" ] = "\t\t&& @"
- language_template[ "ii" ] = "IIF((@),,)"
- language_template[ "if" ] = "IF(@)\n\t\nENDIF"
- language_template[ "ie" ] = "IF(@)\n\t\nELSE\n\t\nENDIF"
- language_template[ "ca" ] = "DO CASE\n\tCASE @\n\t\nOTHERWISE\n \n\b\bENDCASE"
- language_template[ "el" ] = "ELSE\n\t@"
- language_template[ "en" ] = "ENDIF"
- language_template[ "wh" ] = "DO WHILE (@)\n\t\nENDDO"
- language_template[ "do" ] = "DO @ WITH "
- language_template[ "pr" ] = "PROCEDURE @\nPARAMETERS\n\t\nRETURN"
- language_template[ "fu" ] = "FUNCTION @\nPARAMETERS\n\t\nRETURN( )"
- language_template[ "le" ] = "LEN(@)"
- language_template[ "lo" ] = "LOCATE @"
- language_template[ "tr" ] = "TRIM(@)"
- language_template[ "us" ] = "USE @ "
- language_template[ "in" ] = "INDEX @"
- language_template[ "al" ] = "ALIAS @"
- language_template[ "cl" ] = "CLEAR @"
- language_template[ "co" ] = "COPY TO @"
- language_template[ "pv" ] = "PRIVATE @"
- language_template[ "gt" ] = "GO TOP"
- language_template[ "gb" ] = "GO BOTTOM"
- language_template[ "pu" ] = "PUBLIC @"
- language_template[ "de" ] = "DELETE @"
- language_template[ "se" ] = "SELECT @"
- language_template[ "as" ] = "ASC(@)"
- language_template[ "ch" ] = "CHR(@)"
- language_template[ "at" ] = "AT(@,)"
- language_template[ "ct" ] = "CTOD(@)"
- language_template[ "dc" ] = "DTOC(@)"
- language_template[ "cm" ] = "CMONTH(@)"
- language_template[ "dt" ] = "DATE()"
- language_template[ "da" ] = "DAY(@)"
- language_template[ "bf" ] = "BOF()"
- language_template[ "ef" ] = "EOF()"
- language_template[ "ds" ] = "DTOS(@)"
- language_template[ "lo" ] = "LOWER(@)"
- language_template[ "up" ] = "UPPER(@)"
- language_template[ "mi" ] = "MIN(@,)"
- language_template[ "ma" ] = "MAX(@,)"
- language_template[ "mo" ] = "MONTH(@)"
- language_template[ "yr" ] = "YEAR(@)"
- language_template[ "pc" ] = "PCOUNT() = @"
- language_template[ "ra" ] = "RAT(@,)"
- language_template[ "ss" ] = "SAVE SCREEN TO @"
- language_template[ "rs" ] = "RESTORE SCREEN FROM @"
- language_template[ "tf" ] = "TRANSFORM(@,)"
- language_template[ "su" ] = "SUBSTR(@,,)"
- language_template[ "sp" ] = "SPACE(@)"
- language_template[ "re" ] = "REPLICATE(@,)"
- language_template[ "rp" ] = "REPLACE @"
- language_template[ "va" ] = "VAL(@)"
- language_template[ "pi" ] = "PICTURE @"
- language_template[ "vl" ] = "VALID(@)"
- }
- } else if(buffer_name ~ file_extensions["pascal"]) {
- ### Turbo 5.5 / Quick Pascal 1.x compatible templates
-
- if (electric_extensions == file_extensions["pascal"])
- return;
-
- delete( language_template ); # delete last template and start over
- electric_extensions=file_extensions["pascal"]
-
- language_template[ "{" ] = "{@}" # }
- language_template[ "(" ] = "(@)"
- language_template[ "[" ] = "[@]"
- language_template[ "*" ] = "(***\n*** @\n***)"
- language_template[ "if" ] = "IF (@) THEN "
- language_template[ "ie" ] = "IF (@) THEN \n\tELSE "
- language_template[ "fo" ] = "FOR @ := TO DO\nBEGIN\n\t\nEND;"
- language_template[ "ca" ] = "CASE @ OF \n\t\nEND;"
- language_template[ "el" ] = "ELSE @"
- language_template[ "en" ] = "END;"
- language_template[ "re" ] = "REPEAT\n\t\nUNTIL (@);"
- language_template[ "wh" ] = "WHILE (@) DO\nBEGIN\n\t\nEND;"
- language_template[ "be" ] = "BEGIN\n\t@\nEND;"
- language_template[ "pr" ] = "PROCEDURE @();\nBEGIN\n\t\nEND;"
- language_template[ "fu" ] = "FUNCTION @(): ;\nBEGIN\n\t\nEND;"
- } else if ( buffer_name ~ file_extensions["basic"]) {
- ### here if they are needed by anyone
-
- if(electric_extensions == file_extensions["basic"])
- return;
-
- delete( language_template ); # delete last template and start over
- ELEC_LANG = "basic"
- electric_extensions=file_extensions[ELEC_LANG]
-
- language_template[ "null" ] = "\0"
- } else if ( buffer_name ~ file_extensions["asm"] ){
- ### if you need ASM macros
- if(electric_extensions==file_extensions["asm"])
- return;
- delete(language_template);
- ELEC_LANG = "asm"
- electric_extensions=file_extensions[ ELEC_LANG ]
- language_template["null"]="\0"
- } else {
- electric_extensions=file_extensions["text"]
- language_template[ "null" ] = "\0"
- }
- }
-
-
- global function dBaseDialect( dialect ){
- if ( argcount() < 1 ) {
- dialect = tolower( prompt_history(
- "DB_DIALECT",
- "dBase Dialect: ",
- D_DIALECT,
- 1 ))
- } else {
- dialect = tolower(dialect)
- }
- if ( dialect == "clipper50" \
- || dialect == "clipper87" \
- || dialect == "force" \
- || dialect == "dbase" ) {
- D_DIALECT = dialect
- } else {
- D_DIALECT = "dbase"
- warning("Valid choices are 'clipper87' 'clipper50' 'force' 'dbase'(default)")
- }
- ELEC_LANG = D_DIALECT
- }
-
-
- ## template_add()
- #
- # Provides ability to add templates on the fly
- # It is also possible to change a current template with this function
- #
- function template_add( tstr, expstr ) {
- if (argcount() < 1)
- tstr=prompt("Template characters: ","")
- if (tstr && argcount() < 2)
- expstr=prompt("Template expansion: ","")
- if(tstr){
- gsub("\\\\\\\\","\\",expstr)
- language_template[tstr]=expstr
- message("Template \""tstr"\" created.")
- }
- }
-
-
- function extension_add(extstr) {
- if ( argcount() < 1 )
- extstr = prompt_history(
- "EXT_L",
- toupper( ELEC_LANG ) " File Extensions: ",
- file_extensions[ ELEC_LANG],
- 1 )
- if ( extstr ){
- gsub("\\\\\\\\","\\",extstr)
- file_extensions[ ELEC_LANG ] = extstr
- message( toupper(ELEC_LANG) " file extensions updated." )
- }
- }
-
-
-
-
- ## expand_template()
- #
- # Expand a template if one can be located at or near the cursor.
- #
- function expand_template(){
- local l, s, t
-
- initialize_template()
-
- if ( electric_mode && buffer_name ~ electric_extensions ){
- for( t in language_template ){ # [ l ]
- l = length( t ) #
- s = readn( l )
-
- if( t == s ){
- current_column -= l
- delete_chars( l )
- insert_template( language_template[ t ])
- return
- }
- }
- }
- beep()
- }
-
-
-
- ## insert_template()
- #
- # insert a particular template
- #
- # The following characters are treated specially:
- #
- # 1. "@" => place the cursor here after the template has been inserted
- # 2. "\n" => insert a newline and auto-indent.
- # 3. "\r" => insert a newline
- # 4. "\t" => indent an extra level (not actually treated specially)
- # 5. "\b" => unindent one level
- #
- # eg.: "{\n\t\n\b}" follows K&R
-
- local function insert_template( t ){
- local i, c
- local col = current_column
- local row = current_line
- local rs = and(buffer_flags,BUFFER_REAL_SPACE_ONLY);
-
- buffer_flags = and( buffer_flags, not(BUFFER_REAL_SPACE_ONLY) );
-
- while( t && ( i = match( t, "[@\\n\\b]" ))){
-
- if( i > 1 )
- insert_string( substr( t, 1, i - 1 ))
- c = substr( t, i, 1 )
- t = substr( t, i + 1 )
-
- if( c == "\n" ){
- insert_auto_indent()
-
- } else if( c == "\r" ){
- insert_newline_ai()
-
- } else if( c == "\b" ){
- backspace();
-
- } else if( c == "@" ){
- col = current_column
- row = current_line
- }
- }
-
- insert_string( t )
-
- buffer_flags = or( buffer_flags, rs );
-
- goto_pos( row, col )
- }
-
-
- ### support for matching constructs
- #
-
- local matching_pairs = "{ } [ ] ( ) /* */" # string of matching pairs
-
- ## record the particular matching constructs
- #
- # argument is a whitespace-separated sequence of opening, closing pairs
- # a null string causes the defaults to be selected
-
- function init_goto_match( pairs ){
- matching_pairs = pairs
- }
-
-
- ## form an inclusive selection around a matching pair
- #
- # If a selection has already been made, merely swap_marks().
- # It is an error if no half of a matching pair can be found.
-
- function mark_matching(){
- if( region_type() ){
- swap_marks()
- } else {
- save_position()
- if( goto_matching()){
- drop_anchor( INCLUSIVE_SELECTION )
- }
- restore_position( 1 )
- }
- }
-
- function normalize_block(i){}
-
- ## normalize_block
- # Moves cursor to beginning or end of block, if it's not already there.
-
- local function normalize_block(move_to_end)
- {
- if ((mark_line() > mark_line(0)) ||
- ((mark_line() == mark_line(0)) && (mark_column() > mark_column(0))))
- if (move_to_end)
- swap_marks();
- }
-
-
- ## form an inclusive selection around a NESTED matching pair
- #
- function mark_matching_next()
- {
- local s_flag = 0x04 + 0x10;
- if (region_type() != 0){
- normalize_block(0); # move cursor to beginning of block
- raise_anchor();
- next_char();
- }
- if (search("([\\({\\[])|(/\\*)", s_flag) == 0) # "}"
- message("No opening pairs found.");
- else
- mark_matching();
- }
-
-
-
- ## goto the matching construct corresponding to the one under the cursor
- #
- # The cursor may be on a matching construct and be valid.
- # The cursor is restored to its original position if no match is found.
-
- function goto_matching(){
- local forward # odd => forward; even => backward
- local base, open, close
- local l, i, p
- local matching_pair # the array identifying matching pairs
- local matching_count # number of elements in matching_pair
-
- if( matching_pairs ){
-
- matching_count = split( matching_pairs, matching_pair )
-
- for( i=1; i<= matching_count; i++ ){
- p = matching_pair[ i ]
- l = length( p )
- if( p == readn1( l )){ # || p == readn( l )
- forward = and( i, 1 )
- base = and( i + 1, 0xFFFFFFFE )
- open = matching_pair[ base - 1 ]
- close = matching_pair[ base ]
- return scan_for_matching( forward, open, close )
- }
- }
-
- warning( "cursor not positioned on matching construct" )
- }
-
- beep()
-
- return 0
- }
-
- ## move the cursor to a matching construct,
- #
- # given a direction, and the opening and closing constructs.
- # The cursor is restored to its original position if no match is found.
-
-
- local function scan_for_matching( forward, open, close ){
- local olen = length( open )
- local clen = length( close )
- local pattern = quote_regex( open ) "|" quote_regex( close )
- local flags = SEARCH_REGEX \
- + SEARCH_IGNORE_CASE \
- + SEARCH_MAXIMAL_MATCH \
- + SEARCH_ADVANCE \
- + SEARCH_FORWARD * forward
- local level = forward * 2 - 1 # forward => +1; backward => -1
- local s
-
- save_position()
-
- while( level != 0 ){
- if( search( pattern, flags )){
- s = readn1( olen )
- if( s == open ) # == was opening symbol
- level += 1
- if( olen != clen )
- s = readn1( clen )
- if( s == close ) # == was closing symbol
- level -= 1
- } else {
- restore_position( 1 ) # restore saved pos
- warning( "unbalanced nesting pair" )
- beep()
- return 0
- }
- }
-
- restore_position( 0 ) # discard saved pos
-
- return 1
- }
-
-
- ##
- # braces -- report on unmatched opening and closing braces
- #
- function braces(){
- local prevWin = current_window
- local level = 0
- local matched
- local opening = "{"
- local closing = "}"
- local pattern = quote_regex( opening ) "|" quote_regex( closing )
- local flags = SEARCH_FWD_REGEX_MAX_IG
-
- if( dialog_window )
- current_window = dialog_window
-
- save_position()
- goto_buffer_top()
-
- while( search( pattern, flags )){
- matched = read_buffer( search_string_length )
- if( matched == opening ){
- save_position()
- level++
- } else if( matched == closing ){
- if( level-- ){
- restore_position( 0 )
- } else {
- save_position()
- break
- }
- }
- message( "nesting level == " substr( "{{{{{{{{{{...", 1, level )) # }}}}}}}}}}
- next_char()
- }
-
- if( prevWin )
- current_window = prevWin
-
-
- restore_position( 1 )
- if( level > 0 ){
- while( level-- ) {
- restore_position( 0 )
- }
- warning( "unmatched " opening )
- } else if( level < 0 ){
- restore_position( 0 )
- warning( "unmatched " closing )
- } else {
- message( "all braces match" )
- }
- }
-
- # read n characters before the cursor
-
- local function readn( n ){
- return ( n <= current_line_offset ) \
- ? read_buffer( -n ) \
- : ""
- }
-
- # read n characters following and including the cursor
-
- local function readn1( n ){
- return ( n + current_line_offset <= current_line_length ) \
- ? read_buffer( n ) \
- : ""
- }
-
-
- # quote all regex characters in a string
-
- function quote_regex( s ){ #PUBLIC #STR
- local r = s
-
- gsub( "[\\\\.*{}()^$|\\[\\]]", "\\\\&", r )
- return r
- }
-
-
- ### auto indent mode: automatically indent newly-entered lines to match
- # the leading whitespace on the previous non-blank line.
- #
- # One key, normally Enter, causes auto-indent to occur.
- # Another key, normally Control-Enter causes auto-indent to
- # occur after a line is "opened".
- #
- # The automatically-indented line is initially composed of virtual
- # space. This means that consecutive lines that are indented but
- # also left blank do not contain any superfluous characters.
-
-
- global auto_indent_mode = 0
-
- function ai( on ){ #PUBLIC #VOID
- if (argcount())
- toggle_auto_indent( on )
- else
- toggle_auto_indent()
- }
-
- ## toggle auto-indent mode
- # when enabled auto_indent_cr does auto-indenting;
- # when disabled auto_indent_cr merely inserts a "\n".
- #
- # if selection is present it causes the mode to be set to its value
- # rather than toggled
-
- function toggle_auto_indent( selection ){ #PUBLIC #VOID
- local verbose = 0
-
- if( argcount() < 1 ){
- selection = !auto_indent_mode
- verbose = 1
- }
-
- auto_indent_mode = selection
-
- if( verbose )
- message( selection \
- ? "auto-indent enabled" \
- : "auto-indent disabled" )
- }
-
-
- # open line and auto-indent
-
- function auto_indent_nl(){
- goto_eol()
- if( auto_indent_mode )
- insert_auto_indent() # prev_command == function_id( "auto_indent_nl" ))
- else
- insert_newline_ai()
- }
-
-
- # insert a new line and auto-indent
-
- function auto_indent_cr(){
- if( auto_indent_mode )
- insert_auto_indent() # prev_command == function_id( "auto_indent_cr" ))
- else
- insert_newline_ai()
- }
-
- local function insert_newline_ai(){
- local overtypemode = and( buffer_flags, BUFFER_OVERTYPE_MODE );
-
- buffer_flags = and( buffer_flags, not(BUFFER_OVERTYPE_MODE) );
- insert_newline();
- buffer_flags = or( buffer_flags, overtypemode );
- }
-
-
-
- # # insert and auto-indent a newline before the current line
- #
- # function auto_indent_before(){
- # if( current_line == 1 ){
- # goto_bol()
- # insert_newline_ai()
- # up()
- # } else {
- # up()
- # auto_indent_nl()
- # }
- # }
-
- function insert_auto_indent( repeat ){
- local line, col, follow
-
- follow = read_buffer( 100 )
- delete_to_eol()
- insert_newline_ai()
-
- line = current_line
- do {
- prev_line()
- } while( current_line > 1 && !read_buffer( 1 ))
-
- col = current_column
- goto_pos( line, col )
- insert_string( follow )
- goto_pos( line, col )
- }
-
-
- ###
- #
- # electric_edit_file()
- #
- # Whenever a new edit file is created, the extension is stripped from
- # the file name and a function with that extension (preceded by "__")
- # is invoked. If the function does not exist, "_default()" is called.
- #
- global function electric_edit_file() {
- local ext = path_ext( buffer_filename );
- local lev = message_level;
- local def_name = "_default"
- local id
-
- message_level = 3;
-
- if (ext) {
- if (substr( ext, 1, 1 ) == "." ) {
- ext = "__" substr( ext, 2 );
- id = function_id( ext );
- if ( id ) {
- message_level = lev;
- execute_function( ext );
- return;
- }
- }
- }
-
- id = function_id( def_name );
- message_level = lev;
- if ( id )
- execute_function( def_name );
- }
-
-
- #
- # Language-specific macros. The following ("__") macros are called in turn
- # whenever a file with the corresponding (".") extension is edited and
- # electric is enabled.
- #
-
- function __c(){
- buffer_tabs = "5 9" # equidistant 4
- }
-
- function __pel(){
- buffer_tabs = "9 17" # equidistant 8
- }
-
- function __awk(){
- buffer_tabs = "9 17" # equidistant 8
- }
-
- function __cbl(){
- buffer_tabs = "8 12" # 8 followed by equidistant 4
- }
-
- function __cob(){
- buffer_tabs = "8 12" # 8 followed by equidistant 4
- }
-
- function __sal(){
- buffer_tabs = "9 17" # equidistant 8
- }
-
- function __asm(){
- buffer_tabs = "9 17" # equidistant 8
- }
-
- function __prg() {
- buffer_tabs = "5 9" # equidistant 4
- }
-