Parse also sections in configuration files.

Allow whitespace in keys and section names.
Remove unused LexConf.cxx.
Highlight also space separated key value pairs.		 


git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@1656 ea778897-0a13-0410-b9d1-a72fbfd435f5
This commit is contained in:
Enrico Tröger 2007-07-02 17:09:48 +00:00
parent 7cdacb9ef4
commit f651b49c18
8 changed files with 75 additions and 231 deletions

View File

@ -1,3 +1,15 @@
2007-07-02 Enrico Tröger <enrico.troeger@uvena.de>
* src/symbols.c, tagmanager/conf.c:
Parse also sections in configuration files.
Allow whitespace in keys and section names.
* scintilla/makefile.win32, scintilla/KeyWords.cxx,
scintilla/LexConf.cxx, scintilla/Makefile.am:
Remove unused LexConf.cxx.
* scintilla/LexOthers.cxx:
Highlight also space separated key value pairs.
2007-06-29 Enrico Tröger <enrico.troeger@uvena.de>
* src/dialogs.c:

View File

@ -147,7 +147,6 @@ int Scintilla_LinkLexers() {
LINK_LEXER(lmFreeBasic);
LINK_LEXER(lmBatch);
LINK_LEXER(lmCaml);
LINK_LEXER(lmConf);
LINK_LEXER(lmCPP);
LINK_LEXER(lmCPPNoCase);
LINK_LEXER(lmCss);

View File

@ -1,188 +0,0 @@
// Scintilla source code edit control
/** @file LexConf.cxx
** Lexer for Apache Configuration Files.
**
** First working version contributed by Ahmad Zawawi <zeus_go64@hotmail.com> on October 28, 2000.
** i created this lexer because i needed something pretty when dealing
** when Apache Configuration files...
**/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
#include "Platform.h"
#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static void ColouriseConfDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler)
{
int state = SCE_CONF_DEFAULT;
char chNext = styler[startPos];
int lengthDoc = startPos + length;
// create a buffer large enough to take the largest chunk...
char *buffer = new char[length];
int bufferCount = 0;
// this assumes that we have 2 keyword list in conf.properties
WordList &directives = *keywordLists[0];
WordList &params = *keywordLists[1];
// go through all provided text segment
// using the hand-written state machine shown below
styler.StartAt(startPos);
styler.StartSegment(startPos);
for (int i = startPos; i < lengthDoc; i++) {
char ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
if (styler.IsLeadByte(ch)) {
chNext = styler.SafeGetCharAt(i + 2);
i++;
continue;
}
switch(state) {
case SCE_CONF_DEFAULT:
if( ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ') {
// whitespace is simply ignored here...
styler.ColourTo(i,SCE_CONF_DEFAULT);
break;
} else if( ch == '#' ) {
// signals the start of a comment...
state = SCE_CONF_COMMENT;
styler.ColourTo(i,SCE_CONF_COMMENT);
} else if( ch == '.' /*|| ch == '/'*/) {
// signals the start of a file...
state = SCE_CONF_EXTENSION;
styler.ColourTo(i,SCE_CONF_EXTENSION);
} else if( ch == '"') {
state = SCE_CONF_STRING;
styler.ColourTo(i,SCE_CONF_STRING);
} else if( ispunct(ch) ) {
// signals an operator...
// no state jump necessary for this
// simple case...
styler.ColourTo(i,SCE_CONF_OPERATOR);
} else if( isalpha(ch) ) {
// signals the start of an identifier
bufferCount = 0;
buffer[bufferCount++] = static_cast<char>(tolower(ch));
state = SCE_CONF_IDENTIFIER;
} else if( isdigit(ch) ) {
// signals the start of a number
bufferCount = 0;
buffer[bufferCount++] = ch;
//styler.ColourTo(i,SCE_CONF_NUMBER);
state = SCE_CONF_NUMBER;
} else {
// style it the default style..
styler.ColourTo(i,SCE_CONF_DEFAULT);
}
break;
case SCE_CONF_COMMENT:
// if we find a newline here,
// we simply go to default state
// else continue to work on it...
if( ch == '\n' || ch == '\r' ) {
state = SCE_CONF_DEFAULT;
} else {
styler.ColourTo(i,SCE_CONF_COMMENT);
}
break;
case SCE_CONF_EXTENSION:
// if we find a non-alphanumeric char,
// we simply go to default state
// else we're still dealing with an extension...
if( isalnum(ch) || (ch == '_') ||
(ch == '-') || (ch == '$') ||
(ch == '/') || (ch == '.') || (ch == '*') )
{
styler.ColourTo(i,SCE_CONF_EXTENSION);
} else {
state = SCE_CONF_DEFAULT;
chNext = styler[i--];
}
break;
case SCE_CONF_STRING:
// if we find the end of a string char, we simply go to default state
// else we're still dealing with an string...
if( (ch == '"' && styler.SafeGetCharAt(i-1)!='\\') || (ch == '\n') || (ch == '\r') ) {
state = SCE_CONF_DEFAULT;
}
styler.ColourTo(i,SCE_CONF_STRING);
break;
case SCE_CONF_IDENTIFIER:
// stay in CONF_IDENTIFIER state until we find a non-alphanumeric
if( isalnum(ch) || (ch == '_') || (ch == '-') || (ch == '/') || (ch == '$') || (ch == '.') || (ch == '*')) {
buffer[bufferCount++] = static_cast<char>(tolower(ch));
} else {
state = SCE_CONF_DEFAULT;
buffer[bufferCount] = '\0';
// check if the buffer contains a keyword, and highlight it if it is a keyword...
if(directives.InList(buffer)) {
styler.ColourTo(i-1,SCE_CONF_DIRECTIVE );
} else if(params.InList(buffer)) {
styler.ColourTo(i-1,SCE_CONF_PARAMETER );
} else if(strchr(buffer,'/') || strchr(buffer,'.')) {
styler.ColourTo(i-1,SCE_CONF_EXTENSION);
} else {
styler.ColourTo(i-1,SCE_CONF_DEFAULT);
}
// push back the faulty character
chNext = styler[i--];
}
break;
case SCE_CONF_NUMBER:
// stay in CONF_NUMBER state until we find a non-numeric
if( isdigit(ch) || ch == '.') {
buffer[bufferCount++] = ch;
} else {
state = SCE_CONF_DEFAULT;
buffer[bufferCount] = '\0';
// Colourize here...
if( strchr(buffer,'.') ) {
// it is an IP address...
styler.ColourTo(i-1,SCE_CONF_IP);
} else {
// normal number
styler.ColourTo(i-1,SCE_CONF_NUMBER);
}
// push back a character
chNext = styler[i--];
}
break;
}
}
delete []buffer;
}
static const char * const confWordListDesc[] = {
"Directives",
"Parameters",
0
};
LexerModule lmConf(SCLEX_CONF, ColouriseConfDoc, "conf", 0, confWordListDesc);

View File

@ -594,7 +594,8 @@ static void ColourisePropsLine(
while ((i < lengthLine) && isspacechar(lineBuffer[i])) // Skip initial spaces
i++;
if (i < lengthLine) {
if (lineBuffer[i] == '#' || lineBuffer[i] == '!' || lineBuffer[i] == ';') {
if (lineBuffer[i] == '#' || lineBuffer[i] == '!' || lineBuffer[i] == ';' ||
(i < (lengthLine - 1) && lineBuffer[i] == '/' && lineBuffer[i+1] == '/')) {
styler.ColourTo(endPos, SCE_PROPS_COMMENT);
} else if (lineBuffer[i] == '[') {
styler.ColourTo(endPos, SCE_PROPS_SECTION);
@ -605,9 +606,9 @@ static void ColourisePropsLine(
styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
} else {
// Search for the '=' character
while ((i < lengthLine) && (lineBuffer[i] != '='))
while ((i < lengthLine) && ! (lineBuffer[i] == '=' || isspacechar(lineBuffer[i])))
i++;
if ((i < lengthLine) && (lineBuffer[i] == '=')) {
if ((i < lengthLine) && (lineBuffer[i] == '=' || isspacechar(lineBuffer[i]))) {
styler.ColourTo(startLine + i - 1, SCE_PROPS_KEY);
styler.ColourTo(startLine + i, SCE_PROPS_ASSIGNMENT);
styler.ColourTo(endPos, SCE_PROPS_DEFAULT);

View File

@ -14,7 +14,6 @@ LexBash.cxx \
LexOMS.cxx \
LexCPP.cxx \
LexCaml.cxx \
LexConf.cxx \
LexCrontab.cxx \
LexCSS.cxx \
LexD.cxx \

View File

@ -60,7 +60,7 @@ MARSHALLER=scintilla-marshal.o
#++Autogenerated -- run src/LexGen.py to regenerate
#**LEXOBJS=\\\n\(\*.o \)
LEXOBJS=\
LexBash.o LexAsm.o LexCSS.o LexConf.o LexCPP.o LexCrontab.o LexHTML.o LexOthers.o LexPascal.o \
LexBash.o LexAsm.o LexCSS.o LexCPP.o LexCrontab.o LexHTML.o LexOthers.o LexPascal.o \
LexPerl.o LexPython.o LexSQL.o LexCaml.o LexOMS.o LexTCL.o LexRuby.o LexFortran.o LexVHDL.o \
LexD.o LexLua.o LexHaskell.o LexBasic.o
#--Autogenerated -- end of automatically generated section

View File

@ -470,6 +470,12 @@ static void init_tag_list(gint idx)
&tv_iters.tag_function, _("Functions"),
NULL);
break;
case GEANY_FILETYPES_CONF:
tag_list_add_groups(tag_store,
&tv_iters.tag_namespace, _("Sections"),
&tv_iters.tag_macro, _("Keys"),
NULL);
break;
case GEANY_FILETYPES_LATEX:
{
tag_list_add_groups(tag_store,

View File

@ -23,11 +23,13 @@
* DATA DEFINITIONS
*/
typedef enum {
K_NAMESPACE,
K_MACRO
} shKind;
} confKind;
static kindOption ConfKinds [] = {
{ TRUE, 'm', "macro", "macros"}
{ TRUE, 'n', "namespace", "sections"},
{ TRUE, 'm', "macro", "keys"}
};
/*
@ -36,7 +38,8 @@ static kindOption ConfKinds [] = {
static boolean isIdentifier (int c)
{
return (boolean)(isalnum (c) || c == '_');
// allow whitespace within keys and sections
return (boolean)(isalnum (c) || isspace (c) || c == '_');
}
static void findConfTags (void)
@ -46,42 +49,54 @@ static void findConfTags (void)
while ((line = fileReadLine ()) != NULL)
{
const unsigned char* cp = line;
boolean possible = TRUE;
const unsigned char* cp = line;
boolean possible = TRUE;
while (isspace ((int) *cp))
++cp;
if (*cp == '#')
continue;
while (*cp != '\0')
{
/* We look for any sequence of identifier characters following
* either a white space or a colon and followed by either = or :=
*/
if (possible && isIdentifier ((int) *cp))
{
while (isIdentifier ((int) *cp))
{
vStringPut (name, (int) *cp);
++cp;
}
vStringTerminate (name);
while (isspace ((int) *cp))
++cp;
if ( *cp == ':')
++cp;
if ( *cp == '=')
makeSimpleTag (name, ConfKinds, K_MACRO);
vStringClear (name);
}
else if (isspace ((int) *cp) || *cp == ':')
possible = TRUE;
else
possible = FALSE;
if (*cp != '\0')
++cp;
}
++cp;
if (*cp == '#' || (*cp != '\0' && *cp == '/' && *(cp+1) == '/'))
continue;
/* look for a section */
if (*cp != '\0' && *cp == '[')
{
++cp;
while (*cp != '\0' && *cp != ']')
{
vStringPut (name, (int) *cp);
++cp;
}
vStringTerminate (name);
makeSimpleTag (name, ConfKinds, K_NAMESPACE);
vStringClear (name);
continue;
}
while (*cp != '\0')
{
/* We look for any sequence of identifier characters following a white space */
if (possible && isIdentifier ((int) *cp))
{
while (isIdentifier ((int) *cp))
{
vStringPut (name, (int) *cp);
++cp;
}
vStringTerminate (name);
while (isspace ((int) *cp))
++cp;
if (*cp == '=')
makeSimpleTag (name, ConfKinds, K_MACRO);
vStringClear (name);
}
else if (isspace ((int) *cp))
possible = TRUE;
else
possible = FALSE;
if (*cp != '\0')
++cp;
}
}
vStringDelete (name);
}