Added new filetype Haskell (patch by Guillaume Hoffmann, thanks).

git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@1510 ea778897-0a13-0410-b9d1-a72fbfd435f5
This commit is contained in:
Enrico Tröger 2007-05-06 14:05:43 +00:00
parent 45a3a84697
commit 725ae82446
12 changed files with 435 additions and 4 deletions

View File

@ -1,3 +1,12 @@
2007-05-06 Enrico Tröger <enrico.troeger@uvena.de>
* data/filetypes.haskell, scintilla/KeyWords.cxx,
scintilla/LexHaskell.cxx, scintilla/Makefile.am,
scintilla/makefile.win32, src/filetypes.c, src/filetypes.h,
src/highlighting.c, src/highlighting.h, src/sci_cb.c, THANKS:
Added new filetype Haskell (patch by Guillaume Hoffmann, thanks).
2007-05-05 Nick Treleaven <nick.treleaven@btinternet.com>
* src/keybindings.c:

3
THANKS
View File

@ -24,9 +24,10 @@ Josef Whiter <josef(at)toxicpanda(dot)com> - parse 'Entering directory' build me
Jeff Pohlmeyer <yetanothergeek(at)gmail(dot)com> - "Allow DnD", "Use tabs" and other great patches
Tomás Vírseda <kaskaras(at)gmail(dot)com> - sort open files patch
Dirk Weber <dietrich-weber(at)web(dot)de>
Slava Semushin <slava(dot)semushin(at)gmail(dot)com> - patch to improve SVN checks in cofigure script
Slava Semushin <slava(dot)semushin(at)gmail(dot)com> - patch to improve SVN checks in configure script
John Gabriele <jmg3000(at)gmail(dot)com> - documentation patches
Anh Phạm <cs(dot)phamtuananh(at)gmail(dot)com> - various patches
Guillaume Hoffmann <guillaumh(at)gmail(dot)com> - Haskell filetype patch
Translators:
----------------------------------

52
data/filetypes.haskell Normal file
View File

@ -0,0 +1,52 @@
# For complete documentation of this file, please see Geany's main documentation
[styling]
# foreground;background;bold;italic
default=0x000000;0xffffff;false;false
commentline=0x808080;0xffffff;false;false
commentblock=0x808080;0xffffff;false;false
commentblock2=0x808080;0xffffff;false;false
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
[settings]
# the following characters are these which a "word" can contains, see documentation
#wordchars=_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
# if only single comment char is supported like # in this file, leave comment_close blank
comment_open=--
comment_close=
# set to false if a comment character/string should start at column 0 of a line, true uses any
# indentation of the line, e.g. setting to true causes the following on pressing CTRL+d
#command_example();
# setting to false would generate this
# command_example();
# This setting works only for single line comments
comment_use_indent=true
# context action command (please see Geany's main documentation for details)
context_action_cmd=
[build_settings]
# %f will be replaced by the complete filename
# %e will be replaced by the filename without extension
# (use only one of it at one time)
compiler=
linker=
run_cmd=

View File

@ -168,6 +168,7 @@ int Scintilla_LinkLexers() {
LINK_LEXER(lmVHDL);
LINK_LEXER(lmD);
LINK_LEXER(lmLua);
LINK_LEXER(lmHaskell);
//--Autogenerated -- end of automatically generated section

263
scintilla/LexHaskell.cxx Normal file
View File

@ -0,0 +1,263 @@
/******************************************************************
* LexHaskell.cxx
*
* A haskell lexer for the scintilla code control.
* Some stuff "lended" from LexPython.cxx and LexCPP.cxx.
* External lexer stuff inspired from the caml external lexer.
*
* Written by Tobias Engvall - tumm at dtek dot chalmers dot se
*
*
* TODO:
* * Implement a folder :)
* * Nice Character-lexing (stuff inside '\''), LexPython has
* this.
*
*
*****************************************************************/
#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 "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"
#ifdef BUILD_AS_EXTERNAL_LEXER
#include "ExternalLexer.h"
#include "WindowAccessor.h"
#define BUILD_EXTERNAL_LEXER 0
#endif
// Max level of nested comments
#define SCE_HA_COMMENTMAX SCE_HA_COMMENTBLOCK3
enum kwType { kwOther, kwClass, kwData, kwInstance, kwImport, kwModule, kwType};
static inline bool IsNewline(const int ch) {
return (ch == '\n' || ch == '\r');
}
static inline bool IsWhitespace(const int ch) {
return ( ch == ' '
|| ch == '\t'
|| IsNewline(ch) );
}
static inline bool IsAWordStart(const int ch) {
return (ch < 0x80) && (isalnum(ch) || ch == '_');
}
static inline bool IsAWordChar(const int ch) {
return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\'');
}
static void ColorizeHaskellDoc(unsigned int startPos, int length, int initStyle,
WordList *keywordlists[], Accessor &styler) {
WordList &keywords = *keywordlists[0];
int kwLast = kwOther;
StyleContext sc(startPos, length, initStyle, styler);
for (; sc.More(); sc.Forward()) {
// Check for state end
// Operator
if (sc.state == SCE_HA_OPERATOR) {
kwLast = kwOther;
sc.SetState(SCE_HA_DEFAULT);
}
// String
else if (sc.state == SCE_HA_STRING) {
if (sc.ch == '\"') {
sc.ForwardSetState(SCE_HA_DEFAULT);
}
}
// Char
else if (sc.state == SCE_HA_CHARACTER) {
if (sc.ch == '\'') {
sc.ForwardSetState(SCE_HA_DEFAULT);
}
}
// Number
else if (sc.state == SCE_HA_NUMBER) {
if (!IsADigit(sc.ch)) {
sc.SetState(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)) {
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)) {
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;
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;
}
}
}
// Comments
// Oneliner
else if (sc.state == SCE_HA_COMMENTLINE) {
if (IsNewline(sc.ch))
sc.SetState(SCE_HA_DEFAULT);
}
// Nested
else if (sc.state >= SCE_HA_COMMENTBLOCK) {
if (sc.Match("{-")) {
if (sc.state < SCE_HA_COMMENTMAX)
sc.SetState(sc.state + 1);
}
else if (sc.Match("-}")) {
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) {
// Digit
if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
sc.SetState(SCE_HA_NUMBER);
}
// Comment line
else if (sc.Match("--")) {
sc.SetState(SCE_HA_COMMENTLINE);
// Comment block
}
else if (sc.Match("{-")) {
sc.SetState(SCE_HA_COMMENTBLOCK);
}
// String
else if (sc.Match('\"')) {
sc.SetState(SCE_HA_STRING);
}
// Character
else if (sc.Match('\'') && IsWhitespace(sc.GetRelative(-1)) ) {
sc.SetState(SCE_HA_CHARACTER);
}
// 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);
}
// Keyword
else if (IsAWordStart(sc.ch)) {
sc.SetState(SCE_HA_IDENTIFIER);
}
}
}
sc.Complete();
}
// External stuff - used for dynamic-loading, not implemented in wxStyledTextCtrl yet.
// Inspired by the caml external lexer - Credits to Robert Roessler - http://www.rftp.com
#ifdef BUILD_EXTERNAL_LEXER
static const char* LexerName = "haskell";
void EXT_LEXER_DECL Lex(unsigned int lexer, unsigned int startPos, int length, int initStyle,
char *words[], WindowID window, char *props)
{
PropSet ps;
ps.SetMultiple(props);
WindowAccessor wa(window, ps);
int nWL = 0;
for (; words[nWL]; nWL++) ;
WordList** wl = new WordList* [nWL + 1];
int i = 0;
for (; i<nWL; i++)
{
wl[i] = new WordList();
wl[i]->Set(words[i]);
}
wl[i] = 0;
ColorizeHaskellDoc(startPos, length, initStyle, wl, wa);
wa.Flush();
for (i=nWL-1;i>=0;i--)
delete wl[i];
delete [] wl;
}
void EXT_LEXER_DECL Fold (unsigned int lexer, unsigned int startPos, int length, int initStyle,
char *words[], WindowID window, char *props)
{
}
int EXT_LEXER_DECL GetLexerCount()
{
return 1;
}
void EXT_LEXER_DECL GetLexerName(unsigned int Index, char *name, int buflength)
{
if (buflength > 0) {
buflength--;
int n = strlen(LexerName);
if (n > buflength)
n = buflength;
memcpy(name, LexerName, n), name[n] = '\0';
}
}
#endif
LexerModule lmHaskell(SCLEX_HASKELL, ColorizeHaskellDoc, "haskell");

View File

@ -27,7 +27,8 @@ LexPython.cxx \
LexRuby.cxx \
LexSQL.cxx \
LexTCL.cxx \
LexVHDL.cxx
LexVHDL.cxx \
LexHaskell.cxx
SRCS= \
CallTip.cxx \

View File

@ -62,7 +62,7 @@ MARSHALLER=scintilla-marshal.o
LEXOBJS=\
LexBash.o LexAsm.o LexCSS.o LexConf.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
LexD.o LexLua.o LexHaskell.o
#--Autogenerated -- end of automatically generated section
all: $(COMPLIB)

View File

@ -70,7 +70,8 @@ enum
FILETYPE_UID_HTML, // 25
FILETYPE_UID_VHDL, // 26
FILETYPE_UID_JS, // 27
FILETYPE_UID_LUA // 28
FILETYPE_UID_LUA, // 28
FILETYPE_UID_HASKELL // 29
};
@ -113,6 +114,7 @@ filetype *filetypes_get_from_uid(gint uid)
case FILETYPE_UID_VHDL: return filetypes[GEANY_FILETYPES_VHDL];
case FILETYPE_UID_JS: return filetypes[GEANY_FILETYPES_JS];
case FILETYPE_UID_LUA: return filetypes[GEANY_FILETYPES_LUA];
case FILETYPE_UID_HASKELL: return filetypes[GEANY_FILETYPES_HASKELL];
default: return NULL;
}
}
@ -343,6 +345,19 @@ void filetypes_init_types()
filetypes[GEANY_FILETYPES_FERITE]->comment_open = g_strdup("/*");
filetypes[GEANY_FILETYPES_FERITE]->comment_close = g_strdup("*/");
#define HASKELL
filetypes[GEANY_FILETYPES_HASKELL]->id = GEANY_FILETYPES_HASKELL;
filetypes[GEANY_FILETYPES_HASKELL]->uid = FILETYPE_UID_HASKELL;
filetypes[GEANY_FILETYPES_HASKELL]->lang = -2;
filetypes[GEANY_FILETYPES_HASKELL]->name = g_strdup("Haskell");
filetypes[GEANY_FILETYPES_HASKELL]->has_tags = FALSE;
filetypes[GEANY_FILETYPES_HASKELL]->title = g_strdup(_("Haskell source file"));
filetypes[GEANY_FILETYPES_HASKELL]->extension = g_strdup("hs");
filetypes[GEANY_FILETYPES_HASKELL]->pattern = utils_strv_new("*.hs", "*.lhs", NULL);
filetypes[GEANY_FILETYPES_HASKELL]->style_func_ptr = styleset_haskell;
filetypes[GEANY_FILETYPES_HASKELL]->comment_open = g_strdup("--");
filetypes[GEANY_FILETYPES_HASKELL]->comment_close = NULL;
#define SH
filetypes[GEANY_FILETYPES_SH]->id = GEANY_FILETYPES_SH;
filetypes[GEANY_FILETYPES_SH]->uid = FILETYPE_UID_SH;

View File

@ -51,6 +51,7 @@ typedef enum
GEANY_FILETYPES_TCL,
GEANY_FILETYPES_LUA,
GEANY_FILETYPES_FERITE,
GEANY_FILETYPES_HASKELL,
GEANY_FILETYPES_SH,
GEANY_FILETYPES_MAKE,
GEANY_FILETYPES_XML,

View File

@ -2379,6 +2379,79 @@ void styleset_sql(ScintillaObject *sci)
}
static void styleset_haskell_init(void)
{
GKeyFile *config = g_key_file_new();
GKeyFile *config_home = g_key_file_new();
load_keyfiles(config, config_home, GEANY_FILETYPES_HASKELL);
new_style_array(GEANY_FILETYPES_HASKELL, 17);
get_keyfile_hex(config, config_home, "styling", "default", "0x000000", "0xffffff", "false", &style_sets[GEANY_FILETYPES_HASKELL].styling[0]);
get_keyfile_hex(config, config_home, "styling", "commentline", "0x808080", "0xffffff", "false", &style_sets[GEANY_FILETYPES_HASKELL].styling[1]);
get_keyfile_hex(config, config_home, "styling", "commentblock", "0x808080", "0xffffff", "false", &style_sets[GEANY_FILETYPES_HASKELL].styling[2]);
get_keyfile_hex(config, config_home, "styling", "commentblock2", "0x808080", "0xffffff", "false", &style_sets[GEANY_FILETYPES_HASKELL].styling[3]);
get_keyfile_hex(config, config_home, "styling", "commentblock3", "0x808080", "0xffffff", "false", &style_sets[GEANY_FILETYPES_HASKELL].styling[4]);
get_keyfile_hex(config, config_home, "styling", "number", "0x007f00", "0xffffff", "false", &style_sets[GEANY_FILETYPES_HASKELL].styling[5]);
get_keyfile_hex(config, config_home, "styling", "keyword", "0x00007f", "0xffffff", "true", &style_sets[GEANY_FILETYPES_HASKELL].styling[6]);
get_keyfile_hex(config, config_home, "styling", "import", "0x991111", "0xffffff", "false", &style_sets[GEANY_FILETYPES_HASKELL].styling[7]);
get_keyfile_hex(config, config_home, "styling", "string", "0xff901e", "0xffffff", "false", &style_sets[GEANY_FILETYPES_HASKELL].styling[8]);
get_keyfile_hex(config, config_home, "styling", "character", "0xff901e", "0xffffff", "false", &style_sets[GEANY_FILETYPES_HASKELL].styling[9]);
get_keyfile_hex(config, config_home, "styling", "class", "0x0000d0", "0xffffff", "false", &style_sets[GEANY_FILETYPES_HASKELL].styling[10]);
get_keyfile_hex(config, config_home, "styling", "operator", "0x301010", "0xffffff", "false", &style_sets[GEANY_FILETYPES_HASKELL].styling[11]);
get_keyfile_hex(config, config_home, "styling", "identifier", "0x000000", "0xffffff", "false", &style_sets[GEANY_FILETYPES_HASKELL].styling[12]);
get_keyfile_hex(config, config_home, "styling", "instance", "0x000000", "0xffffff", "false", &style_sets[GEANY_FILETYPES_HASKELL].styling[13]);
get_keyfile_hex(config, config_home, "styling", "capital", "0x635b00", "0xffffff", "false", &style_sets[GEANY_FILETYPES_HASKELL].styling[14]);
get_keyfile_hex(config, config_home, "styling", "module", "0x007f7f", "0xffffff", "false", &style_sets[GEANY_FILETYPES_HASKELL].styling[15]);
get_keyfile_hex(config, config_home, "styling", "data", "0x000000", "0xffffff", "false", &style_sets[GEANY_FILETYPES_HASKELL].styling[16]);
style_sets[GEANY_FILETYPES_HASKELL].keywords = g_new(gchar*, 2);
get_keyfile_keywords(config, config_home, "keywords", "keywords", GEANY_FILETYPES_HASKELL, 0,
"as case class data deriving do else if import in infixl infixr instance let module of primitive qualified then type where");
style_sets[GEANY_FILETYPES_HASKELL].keywords[1] = NULL;
get_keyfile_wordchars(config, config_home, &style_sets[GEANY_FILETYPES_HASKELL].wordchars);
filetypes_get_config(config, config_home, GEANY_FILETYPES_HASKELL);
g_key_file_free(config);
g_key_file_free(config_home);
}
void styleset_haskell(ScintillaObject *sci)
{
styleset_common(sci, 5);
if (style_sets[GEANY_FILETYPES_HASKELL].styling == NULL) styleset_haskell_init();
SSM(sci, SCI_SETWORDCHARS, 0, (sptr_t) style_sets[GEANY_FILETYPES_HASKELL].wordchars);
SSM(sci, SCI_AUTOCSETMAXHEIGHT, app->autocompletion_max_height, 0);
SSM(sci, SCI_SETLEXER, SCLEX_HASKELL, 0);
SSM(sci, SCI_SETKEYWORDS, 0, (sptr_t) style_sets[GEANY_FILETYPES_HASKELL].keywords[0]);
set_sci_style(sci, STYLE_DEFAULT, GEANY_FILETYPES_HASKELL, 0);
set_sci_style(sci, SCE_HA_DEFAULT, GEANY_FILETYPES_HASKELL, 0);
set_sci_style(sci, SCE_HA_COMMENTLINE, GEANY_FILETYPES_HASKELL, 1);
set_sci_style(sci, SCE_HA_COMMENTBLOCK, GEANY_FILETYPES_HASKELL, 2);
set_sci_style(sci, SCE_HA_COMMENTBLOCK2, GEANY_FILETYPES_HASKELL, 3);
set_sci_style(sci, SCE_HA_COMMENTBLOCK3, GEANY_FILETYPES_HASKELL, 4);
set_sci_style(sci, SCE_HA_NUMBER, GEANY_FILETYPES_HASKELL, 5);
set_sci_style(sci, SCE_HA_KEYWORD, GEANY_FILETYPES_HASKELL, 6);
set_sci_style(sci, SCE_HA_IMPORT, GEANY_FILETYPES_HASKELL, 7);
set_sci_style(sci, SCE_HA_STRING, GEANY_FILETYPES_HASKELL, 8);
set_sci_style(sci, SCE_HA_CHARACTER, GEANY_FILETYPES_HASKELL, 9);
set_sci_style(sci, SCE_HA_CLASS, GEANY_FILETYPES_HASKELL, 10);
set_sci_style(sci, SCE_HA_OPERATOR, GEANY_FILETYPES_HASKELL, 11);
set_sci_style(sci, SCE_HA_IDENTIFIER, GEANY_FILETYPES_HASKELL, 12);
set_sci_style(sci, SCE_HA_INSTANCE, GEANY_FILETYPES_HASKELL, 13);
set_sci_style(sci, SCE_HA_CAPITAL, GEANY_FILETYPES_HASKELL, 14);
set_sci_style(sci, SCE_HA_MODULE, GEANY_FILETYPES_HASKELL, 15);
set_sci_style(sci, SCE_HA_DATA, GEANY_FILETYPES_HASKELL, 16);
}
static void styleset_caml_init(void)
{
GKeyFile *config = g_key_file_new();
@ -2452,6 +2525,8 @@ void styleset_caml(ScintillaObject *sci)
}
static void styleset_oms_init(void)
{
GKeyFile *config = g_key_file_new();

View File

@ -77,6 +77,8 @@ void styleset_sql(ScintillaObject *sci);
void styleset_caml(ScintillaObject *sci);
void styleset_haskell(ScintillaObject *sci);
void styleset_oms(ScintillaObject *sci);
void styleset_tcl(ScintillaObject *sci);

View File

@ -2102,6 +2102,17 @@ static gboolean is_comment(gint lexer, gint style)
result = TRUE;
break;
}
case SCLEX_HASKELL:
{
if (style == SCE_HA_COMMENTLINE ||
style == SCE_HA_COMMENTBLOCK ||
style == SCE_HA_COMMENTBLOCK2 ||
style == SCE_HA_COMMENTBLOCK3 ||
style == SCE_HA_CHARACTER ||
style == SCE_HA_STRING)
result = TRUE;
break;
}
case SCLEX_HTML:
{
if (style == SCE_HPHP_SIMPLESTRING ||