Dear Geany Hackers,

I am using Haskell for most of my work and I want to have better
syntactic highlighting for it. After I successfully compiled and
installed Geany on my computer I did some fixes in the lexer. The
patch is attached.


This is the list of problems that I fixed:

- some keywords were not listed in filetypes.haskell

- in Haskell there are some words that are keywords only in some
context. For example here:

           import Foo as Bar

  'as' is a keyword but in all other contexts it is a normal
identifier. There are some other keywords like that

- The highligthting was failing if the operators are not separated by
spaces. For example here:

           10+20

  '+' is not highlighted. It worked fine only if I write 10 + 20.

- There was highlighting for data types, classes and instances but it
didn't work correctly. For example:

           class Foo x where ....

  here Foo is highlighted as class name. Unfortunately this worked
correctly only for very simple cases. For example
  this is also correct declaration:

           class Eq x => Foo x where

  but in this case Eq will be highlighted which the right class name
is Foo. Since this case could be solved only by implementing
  a full parser, I just removed this feature. It is not very useful anyway.


I hope that this patch will be added in the main repository. Let me
know if there is some special procedure for sending patches.


Best Regards,
  Krasimir
Index: scintilla/include/SciLexer.h
===================================================================
--- scintilla/include/SciLexer.h	(revision 5106)
+++ scintilla/include/SciLexer.h	(working copy)
@@ -963,17 +963,14 @@
 #define SCE_HA_NUMBER 3
 #define SCE_HA_STRING 4
 #define SCE_HA_CHARACTER 5
-#define SCE_HA_CLASS 6
-#define SCE_HA_MODULE 7
-#define SCE_HA_CAPITAL 8
-#define SCE_HA_DATA 9
-#define SCE_HA_IMPORT 10
-#define SCE_HA_OPERATOR 11
-#define SCE_HA_INSTANCE 12
-#define SCE_HA_COMMENTLINE 13
-#define SCE_HA_COMMENTBLOCK 14
-#define SCE_HA_COMMENTBLOCK2 15
-#define SCE_HA_COMMENTBLOCK3 16
+#define SCE_HA_MODULE 6
+#define SCE_HA_CAPITAL 7
+#define SCE_HA_DATA 8
+#define SCE_HA_OPERATOR 9
+#define SCE_HA_COMMENTLINE 10
+#define SCE_HA_COMMENTBLOCK 11
+#define SCE_HA_COMMENTBLOCK2 12
+#define SCE_HA_COMMENTBLOCK3 13
 #define SCE_T3_DEFAULT 0
 #define SCE_T3_X_DEFAULT 1
 #define SCE_T3_PREPROCESSOR 2
Index: scintilla/LexHaskell.cxx
===================================================================
--- scintilla/LexHaskell.cxx	(revision 5106)
+++ scintilla/LexHaskell.cxx	(working copy)
@@ -7,6 +7,7 @@
  *
  *    Written by Tobias Engvall - tumm at dtek dot chalmers dot se
  *
+ *    Various bug fixes by Krasimir Angelov
  *
  *    TODO:
  *    * Implement a folder :)
@@ -48,9 +49,13 @@
 // Max level of nested comments
 #define SCE_HA_COMMENTMAX SCE_HA_COMMENTBLOCK3
 
+#define SCE_HA_IN_IMPORT1     0x100
+#define SCE_HA_IN_IMPORT2     0x200
+#define SCE_HA_IN_IMPORT3     0x300
+#define SCE_HA_IN_MODULE      0x400
+#define SCE_HA_IN_FFI         0x500
+#define SCE_HA_IN_TYPE        0x600
 
-enum kwType { kwOther, kwClass, kwData, kwInstance, kwImport, kwModule, kwType};
-
 static inline bool IsNewline(const int ch) {
    return (ch == '\n' || ch == '\r');
 }
@@ -73,146 +78,184 @@
                                WordList *keywordlists[], Accessor &styler) {
 
    WordList &keywords = *keywordlists[0];
+   WordList &ffi      = *keywordlists[1];
 
-   int kwLast = kwOther;
-
    StyleContext sc(startPos, length, initStyle, styler);
 
-   for (; sc.More(); sc.Forward()) {
+   while (sc.More()) {
+      int style = sc.state &  0xFF;
+      int mode  = sc.state & ~0xFF;
 
       // Check for state end
+      
          // Operator
-      if (sc.state == SCE_HA_OPERATOR) {
-         kwLast = kwOther;
-         sc.SetState(SCE_HA_DEFAULT);
+      if (style == SCE_HA_OPERATOR) {
+         if (isascii(sc.ch) && isoperator(static_cast<char>(sc.ch))) {
+            sc.Forward();
+         } else {
+            styler.ColourTo(sc.currentPos - 1, style);
+            sc.ChangeState(SCE_HA_DEFAULT);
+         }
       }
          // String
-      else if (sc.state == SCE_HA_STRING) {
+      else if (style == SCE_HA_STRING) {
          if (sc.ch == '\"') {
-            sc.ForwardSetState(SCE_HA_DEFAULT);
+            styler.ColourTo(sc.currentPos, style);
+            sc.ChangeState(SCE_HA_DEFAULT | mode);
          } else if (sc.ch == '\\') {
             sc.Forward();
          }
+         sc.Forward();
       }
          // Char
-      else if (sc.state == SCE_HA_CHARACTER) {
+      else if (style == SCE_HA_CHARACTER) {
          if (sc.ch == '\'') {
-            sc.ForwardSetState(SCE_HA_DEFAULT);
+            styler.ColourTo(sc.currentPos, style);
+            sc.ChangeState(SCE_HA_DEFAULT | mode);
          } else if (sc.ch == '\\') {
             sc.Forward();
          }
+         sc.Forward();
       }
          // Number
-      else if (sc.state == SCE_HA_NUMBER) {
-         if (!IsADigit(sc.ch)) {
-            sc.SetState(SCE_HA_DEFAULT);
+      else if (style == SCE_HA_NUMBER) {
+         if (IsADigit(sc.ch)) {
+            sc.Forward();
+         } else {
+            styler.ColourTo(sc.currentPos - 1, style);
+            sc.ChangeState(SCE_HA_DEFAULT);
          }
       }
-         // Types, constructors, etc.
-      else if (sc.state == SCE_HA_CAPITAL) {
-         if (!IsAWordChar(sc.ch) || sc.ch == '.') {
-            sc.SetState(SCE_HA_DEFAULT);
-         }
-      }
          // Identifier
-      else if (sc.state == SCE_HA_IDENTIFIER) {
-         if (!IsAWordChar(sc.ch)) {
+      else if (style == SCE_HA_IDENTIFIER) {
+         if (IsAWordChar(sc.ch)) {
+            sc.Forward();
+         } else {
             char s[100];
             sc.GetCurrent(s, sizeof(s));
-            int style = SCE_HA_IDENTIFIER;
-            if ((kwLast == kwImport) || (strcmp(s,"qualified") == 0) || (strcmp(s,"as") == 0)) {
-               style = SCE_HA_IMPORT;
-            } else if (keywords.InList(s)) {
+            int new_mode = 0;
+            if (keywords.InList(s)) {
                style = SCE_HA_KEYWORD;
-            } else if (kwLast == kwData) {
-               style = SCE_HA_DATA;
-            } else if (kwLast == kwClass) {
-               style = SCE_HA_CLASS;
-            } else if (kwLast == kwModule) {
-               style = SCE_HA_MODULE;
             } else if (isupper(s[0])) {
-               style = SCE_HA_CAPITAL;
-            }
-            sc.ChangeState(style);
-            sc.SetState(SCE_HA_DEFAULT);
-            if (style == SCE_HA_KEYWORD) {
-               if (0 == strcmp(s, "class"))
-                  kwLast = kwClass;
-               else if (0 == strcmp(s, "data"))
-                  kwLast = kwData;
-               else if (0 == strcmp(s, "instance"))
-                  kwLast = kwInstance;
-               else if (0 == strcmp(s, "import"))
-                  kwLast = kwImport;
-               else if (0 == strcmp(s, "module"))
-                  kwLast = kwModule;
+               if (mode >= SCE_HA_IN_IMPORT1 && mode <= SCE_HA_IN_IMPORT3) {
+                  style    = SCE_HA_MODULE;
+                  new_mode = SCE_HA_IN_IMPORT2;
+               } else if (mode == SCE_HA_IN_MODULE)
+                  style    = SCE_HA_MODULE;
                else
-                  kwLast = kwOther;
-            } else if (style == SCE_HA_CLASS || style == SCE_HA_IMPORT ||
-                       style == SCE_HA_MODULE || style == SCE_HA_CAPITAL ||
-                       style == SCE_HA_DATA || style == SCE_HA_INSTANCE) {
-               kwLast = kwOther;
+                  style = SCE_HA_CAPITAL;
+            } else if (mode == SCE_HA_IN_IMPORT1 &&
+                       strcmp(s,"qualified") == 0) {
+                style    = SCE_HA_KEYWORD;
+                new_mode = SCE_HA_IN_IMPORT1;
+            } else if (mode == SCE_HA_IN_IMPORT2) {
+                if (strcmp(s,"as") == 0) {
+                   style    = SCE_HA_KEYWORD;
+                   new_mode = SCE_HA_IN_IMPORT3;
+               } else if (strcmp(s,"hiding") == 0) {
+                   style     = SCE_HA_KEYWORD;
+               }
+            } else if (mode == SCE_HA_IN_FFI) {
+			   if (ffi.InList(s)) {
+                  style = SCE_HA_KEYWORD;
+                  new_mode = SCE_HA_IN_FFI;
+               }
             }
+            else if (mode == SCE_HA_IN_TYPE) {
+               if (strcmp(s,"family") == 0)
+                  style    = SCE_HA_KEYWORD;
+			}
+            styler.ColourTo(sc.currentPos - 1, style);
+            if (strcmp(s,"import") == 0 && mode != SCE_HA_IN_FFI)
+               new_mode = SCE_HA_IN_IMPORT1;
+            else if (strcmp(s,"module") == 0)
+               new_mode = SCE_HA_IN_MODULE;
+            else if (strcmp(s,"foreign") == 0)
+               new_mode = SCE_HA_IN_FFI;
+            else if (strcmp(s,"type") == 0)
+               new_mode = SCE_HA_IN_TYPE;
+            sc.ChangeState(SCE_HA_DEFAULT | new_mode);
          }
       }
+
          // Comments
             // Oneliner
-      else if (sc.state == SCE_HA_COMMENTLINE) {
-         if (IsNewline(sc.ch))
-            sc.SetState(SCE_HA_DEFAULT);
+      else if (style == SCE_HA_COMMENTLINE) {
+         if (IsNewline(sc.ch)) {
+            styler.ColourTo(sc.currentPos - 1, style);
+            sc.ChangeState(SCE_HA_DEFAULT | mode);
+         } else {
+            sc.Forward();
+         }
       }
             // Nested
-      else if (sc.state >= SCE_HA_COMMENTBLOCK) {
+      else if (style >= SCE_HA_COMMENTBLOCK) {
          if (sc.Match("{-")) {
-            if (sc.state < SCE_HA_COMMENTMAX)
-               sc.SetState(sc.state + 1);
+			styler.ColourTo(sc.currentPos - 1, style);
+            if (style < SCE_HA_COMMENTMAX)
+               sc.ChangeState((style + 1) | mode);
+            sc.Forward(2);
          }
          else if (sc.Match("-}")) {
+            sc.Forward(2);
+            styler.ColourTo(sc.currentPos - 1, style);
+            if (style == SCE_HA_COMMENTBLOCK)
+               sc.ChangeState(SCE_HA_DEFAULT | mode);
+            else
+               sc.ChangeState((style - 1) | mode);
+         } else {
             sc.Forward();
-            if (sc.state == SCE_HA_COMMENTBLOCK)
-               sc.ForwardSetState(SCE_HA_DEFAULT);
-            else
-               sc.ForwardSetState(sc.state - 1);
          }
       }
       // New state?
-      if (sc.state == SCE_HA_DEFAULT) {
+      if (style == SCE_HA_DEFAULT) {
          // Digit
          if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
-            sc.SetState(SCE_HA_NUMBER);
+            styler.ColourTo(sc.currentPos - 1, style);
+            sc.Forward();
+            sc.ChangeState(SCE_HA_NUMBER);
             if (sc.ch == '0' && (sc.chNext == 'X' || sc.chNext == 'x')) { // Match anything starting with "0x" or "0X", too
-               sc.Forward(1);
+               sc.Forward();
             }
          }
          // Comment line
          else if (sc.Match("--")) {
-            sc.SetState(SCE_HA_COMMENTLINE);
+            styler.ColourTo(sc.currentPos - 1, style);
+            sc.Forward(2);
+            sc.ChangeState(SCE_HA_COMMENTLINE | mode);
          // Comment block
          }
          else if (sc.Match("{-")) {
-            sc.SetState(SCE_HA_COMMENTBLOCK);
+            styler.ColourTo(sc.currentPos - 1, style);
+            sc.Forward(2);
+            sc.ChangeState(SCE_HA_COMMENTBLOCK | mode);
          }
          // String
          else if (sc.Match('\"')) {
-            sc.SetState(SCE_HA_STRING);
+            styler.ColourTo(sc.currentPos - 1, style);
+            sc.Forward();
+            sc.ChangeState(SCE_HA_STRING | mode);
          }
          // Character
          else if (sc.Match('\'')) {
-            sc.SetState(SCE_HA_CHARACTER);
+            styler.ColourTo(sc.currentPos - 1, style);
+            sc.Forward();
+            sc.ChangeState(SCE_HA_CHARACTER | mode);
          }
-         // Stringstart
-         else if (sc.Match('\"')) {
-            sc.SetState(SCE_HA_STRING);
-         }
          // Operator
          else if (isascii(sc.ch) && isoperator(static_cast<char>(sc.ch))) {
-            sc.SetState(SCE_HA_OPERATOR);
+            styler.ColourTo(sc.currentPos - 1, style);
+            sc.Forward();
+            sc.ChangeState(SCE_HA_OPERATOR);
          }
          // Keyword
          else if (IsAWordStart(sc.ch)) {
-               sc.SetState(SCE_HA_IDENTIFIER);
+            styler.ColourTo(sc.currentPos - 1, style);
+            sc.Forward();
+            sc.ChangeState(SCE_HA_IDENTIFIER | mode);
+         } else {
+            sc.Forward();
          }
-
       }
    }
    sc.Complete();
Index: src/highlighting.c
===================================================================
--- src/highlighting.c	(revision 5106)
+++ src/highlighting.c	(working copy)
@@ -2365,7 +2365,7 @@
 
 static void styleset_haskell_init(gint ft_id, GKeyFile *config, GKeyFile *config_home)
 {
-	new_styleset(ft_id, 17);
+	new_styleset(ft_id, 13);
 
 	get_keyfile_style(config, config_home, "default", &style_sets[ft_id].styling[0]);
 	get_keyfile_style(config, config_home, "commentline", &style_sets[ft_id].styling[1]);
@@ -2374,20 +2374,17 @@
 	get_keyfile_style(config, config_home, "commentblock3", &style_sets[ft_id].styling[4]);
 	get_keyfile_style(config, config_home, "number", &style_sets[ft_id].styling[5]);
 	get_keyfile_style(config, config_home, "keyword", &style_sets[ft_id].styling[6]);
-	get_keyfile_style(config, config_home, "import", &style_sets[ft_id].styling[7]);
-	get_keyfile_style(config, config_home, "string", &style_sets[ft_id].styling[8]);
-	get_keyfile_style(config, config_home, "character", &style_sets[ft_id].styling[9]);
-	get_keyfile_style(config, config_home, "class", &style_sets[ft_id].styling[10]);
-	get_keyfile_style(config, config_home, "operator", &style_sets[ft_id].styling[11]);
-	get_keyfile_style(config, config_home, "identifier", &style_sets[ft_id].styling[12]);
-	get_keyfile_style(config, config_home, "instance", &style_sets[ft_id].styling[13]);
-	get_keyfile_style(config, config_home, "capital", &style_sets[ft_id].styling[14]);
-	get_keyfile_style(config, config_home, "module", &style_sets[ft_id].styling[15]);
-	get_keyfile_style(config, config_home, "data", &style_sets[ft_id].styling[16]);
+	get_keyfile_style(config, config_home, "string", &style_sets[ft_id].styling[7]);
+	get_keyfile_style(config, config_home, "character", &style_sets[ft_id].styling[8]);
+	get_keyfile_style(config, config_home, "operator", &style_sets[ft_id].styling[9]);
+	get_keyfile_style(config, config_home, "identifier", &style_sets[ft_id].styling[10]);
+	get_keyfile_style(config, config_home, "capital", &style_sets[ft_id].styling[11]);
+	get_keyfile_style(config, config_home, "module", &style_sets[ft_id].styling[12]);
 
-	style_sets[ft_id].keywords = g_new(gchar*, 2);
+	style_sets[ft_id].keywords = g_new(gchar*, 3);
 	get_keyfile_keywords(config, config_home, "keywords", ft_id, 0);
-	style_sets[ft_id].keywords[1] = NULL;
+	get_keyfile_keywords(config, config_home, "ffi", ft_id, 1);
+	style_sets[ft_id].keywords[2] = NULL;
 }
 
 
@@ -2396,6 +2393,7 @@
 	apply_filetype_properties(sci, SCLEX_HASKELL, ft_id);
 
 	sci_set_keywords(sci, 0, style_sets[ft_id].keywords[0]);
+	sci_set_keywords(sci, 1, style_sets[ft_id].keywords[1]);
 
 	set_sci_style(sci, STYLE_DEFAULT, ft_id, 0);
 	set_sci_style(sci, SCE_HA_DEFAULT, ft_id, 0);
@@ -2405,16 +2403,12 @@
 	set_sci_style(sci, SCE_HA_COMMENTBLOCK3, ft_id, 4);
 	set_sci_style(sci, SCE_HA_NUMBER, ft_id, 5);
 	set_sci_style(sci, SCE_HA_KEYWORD, ft_id, 6);
-	set_sci_style(sci, SCE_HA_IMPORT, ft_id, 7);
-	set_sci_style(sci, SCE_HA_STRING, ft_id, 8);
-	set_sci_style(sci, SCE_HA_CHARACTER, ft_id, 9);
-	set_sci_style(sci, SCE_HA_CLASS, ft_id, 10);
-	set_sci_style(sci, SCE_HA_OPERATOR, ft_id, 11);
-	set_sci_style(sci, SCE_HA_IDENTIFIER, ft_id, 12);
-	set_sci_style(sci, SCE_HA_INSTANCE, ft_id, 13);
-	set_sci_style(sci, SCE_HA_CAPITAL, ft_id, 14);
-	set_sci_style(sci, SCE_HA_MODULE, ft_id, 15);
-	set_sci_style(sci, SCE_HA_DATA, ft_id, 16);
+	set_sci_style(sci, SCE_HA_STRING, ft_id, 7);
+	set_sci_style(sci, SCE_HA_CHARACTER, ft_id, 8);
+	set_sci_style(sci, SCE_HA_OPERATOR, ft_id, 9);
+	set_sci_style(sci, SCE_HA_IDENTIFIER, ft_id, 10);
+	set_sci_style(sci, SCE_HA_CAPITAL, ft_id, 11);
+	set_sci_style(sci, SCE_HA_MODULE, ft_id, 12);
 }
 
 
Index: data/filetypes.haskell
===================================================================
--- data/filetypes.haskell	(revision 5106)
+++ data/filetypes.haskell	(working copy)
@@ -8,20 +8,17 @@
 commentblock3=0x808080;0xffffff;false;false
 number=0x007f00;0xffffff;false;false
 keyword=0x00007f;0xffffff;true;false
-import=0x991111;0xffffff;false;false
 string=0xff901e;0xffffff;false;false
 character=0x7f007f;0xffffff;false;false
-class=0x0000d0;0xffffff;false;false
 operator=0x301010;0xffffff;false;false
 identifier=0x000000;0xffffff;false;false
-instance=0x000000;0xffffff;false;false
 capital=0x635b00;0xffffff;false;false
 module=0x007f7f;0xffffff;false;false
-data=0x000000;0xffffff;false;false
 
 [keywords]
 # all items must be in one line
-keywords=as case class data deriving do else if import in infixl infixr instance let module of primitive qualified then type where
+keywords=case class data default deriving do else if import in infix infixl infixr instance let module newtype of then type where forall mdo foreign rec proc
+ffi=import export label dynamic safe threadsafe unsafe stdcall ccall dotnet
 
 
 [settings]
_______________________________________________
Geany-devel mailing list
[email protected]
http://lists.uvena.de/cgi-bin/mailman/listinfo/geany-devel

Reply via email to