[Geany-Devel] Interested making a patch to add QML support
Tory Gaurnier
torygaurnier at xxxxx
Tue Sep 24 23:18:14 UTC 2013
On 09/24/2013 01:10 PM, Tory Gaurnier wrote:
> Well, I've pretty much got it working, the highlighting is working,
> and the Javascript functions show up in the symbol list, it's just not
> showing the QML Objects, so once I get that fixed it'll be finished,
> at least the first version, I'm sure I'll want to improve it in the
> future.
Ok, so now I really am at a loss, my qml.c file works fine in Ctags, but
in Geany it only adds the Javascript functions to the symbol list, I
really can't figure it out. I've looked over everything, I've compared
the differences from Ctags in Geany to the original Ctags, the only real
change that makes a difference that I can see is the fact that the type
for filePosition was changed to MIOPos. I'm pretty sure I've edited the
different config files correctly, everythings working except for the QML
Objects. Now when I'm running Geany I'm running in terminal and there
are 0 errors being printed.
Here's my qml.c file:
#include "general.h" /* always include first */
#include "entry.h"
#include "parse.h" /* always include */
#include "read.h" /* to define file fileReadLine() */
#include <string.h> /* to declare strxxx() functions */
typedef struct {
vString *id;
vString *kind;
vString *name;
unsigned long line_num;
MIOPos file_pos; // THIS IS THE ONLY THING I'VE CHANGED FROM THE
CTAGS VERSION
char *kind_name;
char kind_letter;
} QMLObject;
typedef enum {
QML_OBJECT,
JS_FUNCTION,
KIND_COUNT
} QMLKind;
static kindOption QMLKinds[KIND_COUNT] = {
{ TRUE, 'o', "object", "objects" },
{ TRUE, 'f', "function", "functions" }
};
const unsigned char* skipMultilineComment(const unsigned char *line) {
boolean found = FALSE;
while(*line != '\0') {
if(strncmp(line, "*/", 2) == 0) {
line += 2;
found = TRUE;
break;
}
line++;
}
if(found) line = NULL;
return line;
}
void createQMLObjectTag(QMLObject *qml_obj, boolean *is_qml_object) {
tagEntryInfo entry;
// Added this line here to test, and it's printing fine, all values
are there
printf("%s - %d - %s - %c\n", qml_obj->name->buffer,
(int)qml_obj->line_num, qml_obj->kind_name, qml_obj->kind_letter);
initTagEntry(&entry, qml_obj->name->buffer);
entry.lineNumber = qml_obj->line_num;
entry.filePosition = qml_obj->file_pos;
entry.kindName = qml_obj->kind_name;
entry.kind = qml_obj->kind_letter;
makeTagEntry(&entry); // WHY YOU NO MAKE TAG IN SYMBOL LIST!!!! >_<
vStringClear(qml_obj->name);
vStringDelete(qml_obj->name);
*is_qml_object = FALSE;
}
vString* getName(const unsigned char **str_ptr) {
vString *name = vStringNew();
const unsigned char *str = *str_ptr;
while(isalnum(*str) || *str == '_') {
vStringPut(name, *str);
str++;
}
*str_ptr = str;
vStringTerminate(name);
return name;
}
vString *getId(const unsigned char *str, vString *name) {
vString *id = vStringNew();
while(strstr(str, "id:") != NULL) {
if(strncmp(str, "id:", 3) == 0) {
str += 3;
while(isspace(*str)) str++;
id = getName(&str);
vStringCatS(name, " ");
vStringCat(name, id);
}
else str++;
}
vStringClear(id);
vStringDelete(id);
return name;
}
static void findQMLTags(void) {
vString *js_name;
QMLObject *qml_obj = malloc(sizeof(QMLObject));
const unsigned char *line;
boolean is_multiline_comment = FALSE;
boolean is_qml_object = FALSE;
while((line = fileReadLine()) != NULL) {
// If in middle of multiline comment, skip through till end
if(is_multiline_comment) {
if((line = skipMultilineComment(line)) == NULL) continue;
else is_multiline_comment = FALSE;
}
// Skip whitespace and comments
while(isspace(*line)) line++;
if(strncmp(line, "//", 2) == 0) continue;
if(strncmp(line, "/*", 2) == 0) {
is_multiline_comment = TRUE;
if((line = skipMultilineComment(line)) == NULL) continue;
else is_multiline_comment = FALSE;
}
// If in middle of QML Object { } check for ID and '}'
if(is_qml_object && (strstr(line, "id:") != NULL ||
strchr(line, '}') != NULL)) {
if(strstr(line, "id:") != NULL)
qml_obj->name = getId(line, qml_obj->name);
else createQMLObjectTag(qml_obj, &is_qml_object);
}
// If '{' in line, but '(' not in line, then there might be a
QML Object
if(strchr(line, '{') != NULL && strchr(line, '(') == NULL) {
int i = 0;
while(isspace(*line)) line++; // Increment ptr past any
whitespace before 'Object {'
// Search past whole word of 'Object'
while(!isspace(line[i])) {
if(line[i] == '{' || line[i] == ':') break;
i++;
}
while(isspace(line[i])) i++; // Search past any space
between 'Object' and '{'
// If '{' is after potential Object name and any
whitespace, prepare tag to be added
if(line[i] == '{') {
qml_obj->name = getName(&line);
qml_obj->line_num = File.lineNumber;
qml_obj->file_pos = File.filePosition;
qml_obj->kind_name = (char*)QMLKinds[QML_OBJECT].name;
qml_obj->kind_letter = QMLKinds[QML_OBJECT].letter;
qml_obj->kind = QML_OBJECT;
is_qml_object = TRUE;
// If ID is on same line
if(strstr(line, "id:") != NULL) {
while(strncmp(line, "id:", 3) != 0) line++;
qml_obj->name = getId(line, qml_obj->name);
}
// If single line Object
if(strchr(line, '}') != NULL)
createQMLObjectTag(qml_obj, &is_qml_object);
}
}
// If line contains a function
// Using while to prepare for unlikely event that "function"
appears more than once in line
while(strstr(line, "function") != NULL) {
while(strncmp(line, "function", 8) != 0) line++;
// If whitespace is after "function"
if(isspace(line[8])) {
line += 8; // Skip past "function"
while(isspace(*line)) line++;
vString *name = getName(&line);
while(isspace(*line)) line++;
// If '(' is after "function" and whitespace, then add
tag as JS_FUNCTION
if(*line == '(') makeSimpleTag(name, QMLKinds,
JS_FUNCTION);
vStringClear(name);
vStringDelete(name);
break;
}
else line++;
}
}
}
extern parserDefinition *QMLParser(void) {
parserDefinition* def = parserNew("QML");
static const char *const extensions [] = { "qml", NULL };
def->kinds = QMLKinds;
def->kindCount = KIND_COUNT(QMLKinds);
def->extensions = extensions;
def->parser = findQMLTags;
def->regex = FALSE;
return def;
}
More information about the Devel
mailing list