Hi all, For my sins, I'm obliged to develop code in R, and a while back I added in a tagmanager parser for R symbols. The parser is not mine, but is GPLed and the copyright message is intact so I don't expect that to pose a problem for the project.
I've attached a patch against geany-svn which appears to build and function. I'd love to see this become part of the official release. It'd help me promote the use of geany within my company and allow me to go back to letting Fedora do all my upgrades! :-) Jon
Index: src/filetypes.c
===================================================================
--- src/filetypes.c (revision 4673)
+++ src/filetypes.c (working copy)
@@ -574,7 +574,7 @@
#define R
ft = filetypes[GEANY_FILETYPES_R];
- ft->lang = 34;
+ ft->lang = 40;
ft->name = g_strdup("R");
ft->title = g_strdup_printf(_("%s script file"), "R");
ft->extension = g_strdup("R");
Index: src/symbols.c
===================================================================
--- src/symbols.c (revision 4673)
+++ src/symbols.c (working copy)
@@ -650,6 +650,14 @@
NULL);
break;
}
+ case GEANY_FILETYPES_R:
+ {
+ tag_list_add_groups(tag_store,
+ &(tv_iters.tag_function), _("Functions"), "classviewer-method",
+ &(tv_iters.tag_struct), _("Other"), NULL,
+ NULL);
+ break;
+ }
case GEANY_FILETYPES_PERL:
{
tag_list_add_groups(tag_store,
Index: tagmanager/parsers.h
===================================================================
--- tagmanager/parsers.h (revision 4673)
+++ tagmanager/parsers.h (working copy)
@@ -54,7 +54,8 @@
MarkdownParser, \
Txt2tagsParser, \
AbcParser, \
- VerilogParser
+ VerilogParser, \
+ RParser
/*
langType of each parser
0 CParser
@@ -97,6 +98,7 @@
37 Txt2tagsParser
38 AbcParser
39 Verilog
+40 RParser
*/
#endif /* _PARSERS_H */
Index: tagmanager/makefile.win32
===================================================================
--- tagmanager/makefile.win32 (revision 4673)
+++ tagmanager/makefile.win32 (working copy)
@@ -45,7 +45,7 @@
options.o \
parse.o basic.o read.o sort.o strlist.o latex.o markdown.o matlab.o docbook.o tcl.o ruby.o asm.o sql.o txt2tags.o css.o \
vstring.o regex.o tm_workspace.o tm_work_object.o tm_source_file.o tm_project.o tm_tag.o \
-tm_symbol.o tm_file_entry.o tm_tagmanager.o
+tm_symbol.o tm_file_entry.o tm_tagmanager.o r.o
$(AR) rc $@ $^
$(RANLIB) $@
Index: tagmanager/r.c
===================================================================
--- tagmanager/r.c (revision 0)
+++ tagmanager/r.c (revision 0)
@@ -0,0 +1,199 @@
+/*
+* $Id: $
+*
+* Copyright (c) 2003-2004, Ascher Stefan <[email protected]>
+*
+* This source code is released for free distribution under the terms of the
+* GNU General Public License.
+*
+* This module contains functions for generating tags for R language files.
+* R is a programming language for statistical computing.
+* R is GPL Software, get it from http://www.r-project.org/
+*/
+
+/*
+* INCLUDE FILES
+*/
+#include "general.h" /* must always come first */
+
+#include <string.h>
+#include <ctype.h> /* to define isalpha(), isalnum(), isspace() */
+
+#include "entry.h"
+#include "read.h"
+#include "vstring.h"
+
+//#define R_REGEX
+
+#define SKIPSPACE(ch) while (isspace((int)*ch)) \
+ ch++
+
+#ifndef R_REGEX
+static kindOption RKinds [] = {
+ { TRUE, 'f', "function", "functions" },
+ { TRUE, 'l', "other", "libraries" },
+ { TRUE, 's', "other", "source file" }
+};
+#endif
+
+#ifdef R_REGEX
+static void installRRegex (const langType language)
+{
+ /* This is a function, looks as follows:
+ * itent <- function(arg1, arg2) {
+ * do_something;
+ * }
+ */
+ addTagRegex (language,
+ "^[ \t]*([.a-zA-Z0-9_]+)([ \t]*)<-([ \t]*)function", "\\1", "f,function", NULL);
+ /* This loads someting, e.g. a library, simply: library(libname) */
+ addTagRegex (language,
+ "^[ \t]*(library|source|load|data)[\\(]([a-zA-Z0-9_]+)[\\)]", "\\2", "l,load", NULL);
+}
+#else
+static void makeRTag(const vString* const name, int kind)
+{
+ tagEntryInfo e;
+ initTagEntry(&e, vStringValue(name));
+
+ e.kindName = RKinds[kind].name;
+ e.kind = RKinds[kind].letter;
+
+ makeTagEntry(&e);
+}
+
+extern void createRTags(void)
+{
+ vString *vLine = vStringNew();
+ vString *name = vStringNew();
+ char c;
+ int ikind;
+
+ const char *line;
+ while ((line = fileReadLine()) != NULL)
+ {
+ const unsigned char *cp = (const unsigned char*)line;
+
+ vStringClear(name);
+ while ((*cp != '\0') && (*cp != '#')) {
+ /* iterate to the end of line or to a comment */
+ ikind = -1;
+ switch (*cp) {
+ case 'l':
+ case 's':
+ if (strncasecmp((const char*)cp, "library", (size_t)7) == 0) {
+ /* load a library: library(tools) */
+ cp += 7;
+ SKIPSPACE(cp);
+ if (*cp == '(')
+ ikind = 1;
+ else
+ cp -= 7;
+ } else if (strncasecmp((const char*)cp, "source", (size_t)6) == 0) {
+ /* load a source file: source("myfile.r") */
+ cp += 6;
+ SKIPSPACE(cp);
+ if (*cp == '(')
+ ikind = 2;
+ else
+ cp -= 6;
+ }
+ if (ikind != -1) {
+ cp++;
+
+ vStringClear(name);
+ while ((!isspace((int)*cp)) && *cp != '\0' && *cp != ')') {
+ vStringPut(name, (int)*cp);
+ cp++;
+ }
+ vStringTerminate(name);
+
+ /* if the string really exists, make a tag of it */
+ if (vStringLength(name) > 0)
+ makeRTag(name, ikind);
+
+ /* prepare for the next iteration */
+ vStringClear(name);
+ } else {
+ vStringPut(name, (int)*cp);
+ cp++;
+ }
+ break;
+ case '<':
+ cp++;
+ if (*cp == '-') {
+ /* assignment: ident <- someval */
+ cp++;
+ SKIPSPACE(cp);
+
+ if (*cp == '\0') {
+ /* not in this line, read next */
+ /* sometimes functions are declared this way:
+ ident <-
+ function(...)
+ {
+ ...
+ }
+ I don't know if there is a reason to write the function keyword
+ in a new line
+ */
+ if ((line = fileReadLine()) != NULL) {
+ cp = (const unsigned char*)line;
+ SKIPSPACE(cp);
+ }
+ }
+
+ if (strncasecmp((const char*)cp, "function", (size_t)8) == 0) {
+ /* it's a function: ident <- function(args) */
+ cp += 8;
+ vStringTerminate(name);
+ /* if the string really exists, make a tag of it */
+ if (vStringLength(name) > 0)
+ makeRTag(name, 0);
+
+ /* prepare for the next iteration */
+ vStringClear(name);
+ break;
+ }
+ }
+ case ' ':
+ case '\x009':
+ /* skip whitespace */
+ cp++;
+ break;
+ default:
+ /* collect all characters that could be a part of an identifier */
+ vStringPut(name, (int)*cp);
+ cp++;
+ break;
+ }
+ }
+ }
+
+ vStringDelete(name);
+ vStringDelete(vLine);
+}
+#endif
+
+extern parserDefinition* RParser (void)
+{
+ /* *.r: R files
+ * *.s;*.q: S files
+ */
+ static const char *const extensions [] = { "r", "s", "q", NULL };
+ parserDefinition* const def = parserNew ("R");
+#ifndef R_REGEX
+ def->kinds = RKinds;
+ def->kindCount = 4;
+#endif
+ def->extensions = extensions;
+#ifndef R_REGEX
+ def->parser = createRTags;
+#else
+ def->initialize = installRRegex;
+ def->regex = TRUE;
+#endif
+ return def;
+}
+
+/* vi:set tabstop=8 shiftwidth=4: */
Index: tagmanager/Makefile.am
===================================================================
--- tagmanager/Makefile.am (revision 4673)
+++ tagmanager/Makefile.am (working copy)
@@ -67,6 +67,7 @@
verilog.c\
actionscript.c\
nsis.c\
+ r.c \
ctags.c\
entry.c\
get.c\
signature.asc
Description: PGP signature
_______________________________________________ Geany-devel mailing list [email protected] http://lists.uvena.de/cgi-bin/mailman/listinfo/geany-devel
