Notepad++ syntax coloring

Lately, my external editor of choice has been Notepad++. It’s flexible, highly configurable, and supports user-defined syntax coloring. Of course, it doesn’t ship with a syntax coloring file for VFP, so I came up with my own. After a while, I got tired of typing in commands as I got to them, and wrote a program to generate the whole thing.

I copied most of the XML out of my half-completed file, and only substituted in the keywords. I had to specify the folding keywords manually, since FoxCode.dbf doesn’t have any concept of folding. A couple of places the whole thing fell down were comments, since comments and multiplication share the asterisk, and quotes, since VFP uses so many different delimiters. I basically shrugged on these and went “Oh, well” — if you know a better way to handle it, please let me know. :-)

Once you have the file generated, either copy it into Notepad’s APPDATA directory, or copy the Fox-specific code out of the file and paste it in to the existing userdefinelang.xml. From there, you can tweak the fonts, sizes, and colors within N++, which automatically saves the UDL changes on exit.

#DEFINE USERNAME "gfitzgerald"
#DEFINE APPDATAPATH "C:\Documents and Settings\" + USERNAME + "\Application Data\Microsoft\Visual FoxPro 9\foxcode.dbf"

LOCAL loWordsUsed ;
	, lcWords1, lcWords2, lcWords3 ;
	, lcCurrWord ;
	, lcUserDefLang

USE APPDATAPATH ;
	AGAIN ;
	SHARED ;
	IN 0 ;
	ALIAS MyFoxCode

SELECT abbrev, expanded ;
	FROM MyFoxCode ;
	INTO CURSOR crsrFoxFuncs ;
	WHERE type = 'F' ;
		AND RIGHT(UPPER(ALLTRIM(expanded)), 3) != "TIP" ;
		AND VAL(RIGHT(ALLTRIM(expanded), 1)) = 0 ;
	ORDER BY expanded

loWordsUsed = CREATEOBJECT("Collection")

STORE "" TO lcWords1, lcWords2, lcWords3
lcFolder1 = " IF TEXT PROCEDURE DEFINE FOR FUNCTION WITH TRY SCAN "
lcFolder2 = " ENDIF ENDTEXT ENDPROC ENDDEFINE ENDFOR ENDFUNC ENDWITH ENDTRY ENDSCAN "
lcWords4 = " AND OR NOT .T. .F. .NULL. "

SELECT crsrFoxFuncs
SCAN
	lcAbbrev = UPPER(ALLTRIM(abbrev))
	lcExpand = UPPER(ALLTRIM(expanded))
	lcWords1 = lcWords1 ;
		+ IIF(EMPTY(lcAbbrev), "", lcAbbrev + " ") ;
		+ IIF(lcAbbrev == lcExpand, "", lcExpand + " ")
ENDSCAN 

SELECT abbrev, expanded, tip ;
	FROM myFoxCode ;
	INTO CURSOR crsrFoxCmds ;
	WHERE type = 'C' ;
		AND VAL(RIGHT(ALLTRIM(expanded), 1)) = 0 ;
	ORDER BY expanded

SELECT crsrFoxCmds
SCAN
	lcCurrAbbrev = UPPER(ALLTRIM(abbrev))
	IF NOT EMPTY(lcCurrAbbrev) ;
			AND loWordsUsed.GetKey(lcCurrAbbrev) = 0 ;
			AND NOT " " + lcCurrAbbrev + " " $ lcFolder1 ;
			AND NOT " " + lcCurrAbbrev + " " $ lcFolder2 ;
			AND NOT " " + lcCurrAbbrev + " " $ lcWords4
		lcWords2 = lcWords2 + lcCurrAbbrev + " "
		loWordsUsed.Add(.T., lcCurrAbbrev)
	ENDIF

	FOR i = 1 TO GETWORDCOUNT(expanded)
		lcCurrWord = UPPER(ALLTRIM(GETWORDNUM(expanded, i)))
		IF loWordsUsed.GetKey(lcCurrWord) = 0 ;
				AND NOT " " + lcCurrWord + " " $ lcFolder1 ;
				AND NOT " " + lcCurrWord + " " $ lcFolder2 ;
				AND NOT " " + lcCurrWord + " " $ lcWords4
			IF i = 1
				lcWords2 = lcWords2 + lcCurrWord + " "
			ELSE
				lcWords3 = lcWords3 + lcCurrWord + " "
			ENDIF

			loWordsUsed.Add(.T., lcCurrWord)
		ENDIF
	ENDFOR 

	IF NOT EMPTY(tip)
		FOR i = 1 TO GETWORDCOUNT(tip)
			lcTipWord = ALLTRIM(CHRTRAN(GETWORDNUM(tip, i), "[]", "  "))
			IF NOT EMPTY(lcTipWord) ;
					AND NOT " " + lcTipWord + " " $ lcFolder1 ;
					AND NOT " " + lcTipWord + " " $ lcFolder2 ;
					AND NOT " " + lcTipWord + " " $ lcWords4
				llAllUpper = .T.
				FOR j = 1 TO LEN(lcTipWord)
					lcTipLetter = SUBSTR(lcTipWord, j, 1)
					IF NOT(ISALPHA(lcTipLetter) AND ISUPPER(lcTipLetter))
						llAllUpper = .F.
					ENDIF
				ENDFOR
				IF llAllUpper AND loWordsUsed.GetKey(lcTipWord) = 0
					lcWords3 = lcWords3 + lcTipWord + " "
					loWordsUsed.Add(.T., lcTipWord)
				ENDIF
			ENDIF
		ENDFOR
	ENDIF
ENDSCAN

ALINES(laWords3, lcWords3, 1, " ")
ASORT(laWords3)
lcWords3 = ""
FOR i = 1 TO ALEN(laWords3, 1)
	lcWords3 = lcWords3 + laWords3[i] + " "
ENDFOR
lcWords3 = RTRIM(lcWords3)

TEXT TO lcUserDefLang TEXTMERGE NOSHOW
<NotepadPlus>
    <UserLang name="Visual FoxPro" ext="PRG prg">
        <Settings>
            <Global caseIgnored="yes" />
            <TreatAsSymbol comment="no" commentLine="yes" />
            <Prefix words1="no" words2="no" words3="no" words4="no" />
        </Settings>
        <KeywordLists>
            <Keywords name="Delimiters">{00}00</Keywords>
            <Keywords name="Folder+"><<ALLTRIM(lcFolder1)>></Keywords>
            <Keywords name="Folder-"><<ALLTRIM(lcFolder2)>></Keywords>
            <Keywords name="Operators">- ! $ ( ) * , / ; ? [ ] ^ + < = ></Keywords>
            <Keywords name="Comment">1 2 0&& 0NOTE</Keywords>
            <Keywords name="Words1"><<lcWords1>></Keywords>
            <Keywords name="Words2"><<lcWords2>></Keywords>
            <Keywords name="Words3"><<lcWords3>></Keywords>
            <Keywords name="Words4"><<ALLTRIM(lcWords4)>></Keywords>
        </KeywordLists>
        <Styles>
            <WordsStyle name="DEFAULT" styleID="11" fgColor="000000" bgColor="FFFFFF" fontName="Consolas" fontStyle="0" fontSize="12" />
            <WordsStyle name="FOLDEROPEN" styleID="12" fgColor="0000FF" bgColor="FFFFFF" fontName="Consolas" fontStyle="0" fontSize="12" />
            <WordsStyle name="FOLDERCLOSE" styleID="13" fgColor="0000FF" bgColor="FFFFFF" fontName="Consolas" fontStyle="0" fontSize="12" />
            <WordsStyle name="KEYWORD1" styleID="5" fgColor="0000FF" bgColor="FFFFFF" fontName="Consolas" fontStyle="0" fontSize="12" />
            <WordsStyle name="KEYWORD2" styleID="6" fgColor="0000FF" bgColor="FFFFFF" fontName="Consolas" fontStyle="0" fontSize="12" />
            <WordsStyle name="KEYWORD3" styleID="7" fgColor="0000FF" bgColor="FFFFFF" fontName="Consolas" fontStyle="0" fontSize="12" />
            <WordsStyle name="KEYWORD4" styleID="8" fgColor="FF0000" bgColor="FFFFFF" fontName="Consolas" fontStyle="1" fontSize="12" />
            <WordsStyle name="COMMENT" styleID="1" fgColor="000840" bgColor="FFFFFF" fontName="Consolas" fontStyle="2" fontSize="10" />
            <WordsStyle name="COMMENT LINE" styleID="2" fgColor="008040" bgColor="FFFFFF" fontName="Consolas" fontStyle="2" fontSize="10" />
            <WordsStyle name="NUMBER" styleID="4" fgColor="008000" bgColor="FFFFFF" fontName="Consolas" fontStyle="0" fontSize="12" />
            <WordsStyle name="OPERATOR" styleID="10" fgColor="800000" bgColor="FFFFFF" fontName="Consolas" fontStyle="1" fontSize="12" />
            <WordsStyle name="DELIMINER1" styleID="14" fgColor="FFFFFF" bgColor="804000" fontName="Consolas" fontStyle="0" fontSize="12" />
            <WordsStyle name="DELIMINER2" styleID="15" fgColor="FFFFFF" bgColor="804000" fontName="Consolas" fontStyle="0" fontSize="12" />
            <WordsStyle name="DELIMINER3" styleID="16" fgColor="000000" bgColor="FFFFFF" fontName="Consolas" fontStyle="0" />
        </Styles>
    </UserLang>
</NotepadPlus>
ENDTEXT 

STRTOFILE(lcUserDefLang, "userdefinelang.xml")

Posted by Garrett on October 28th, 2008 in Code Sample, Original, VFP | 3 Comments

3 Comments »

  1. I am too lazy to do it manually and not smart enough to do it your way…
    What can I say – thank you! :-)

    Comment by Andrzej — October 29, 2008 @ 5:16 am

  2. Hey Garret,
    Thanks for the code!

    Comment by Cetin Basoz — June 16, 2009 @ 10:40 am

  3. Hi, Garret!

    Thank you for your code,

    I have found VFP syntax for Notepad++ for long time, But I have not capablity to generate XML file with your code. Bother you can help me make a XML of this code and send it to my email (orphenmds#163.com) if you are convenience.

    Your cooperation will be appreciated.

    Comment by Oswald — June 27, 2009 @ 9:20 am

RSS feed for comments on this post. TrackBack URL

Leave a comment