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 <stievie@utanet.at>
+*
+*   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\
