Add Markdown filetype (patch by Jon Strait, thanks).

git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@4046 ea778897-0a13-0410-b9d1-a72fbfd435f5
This commit is contained in:
Nick Treleaven 2009-07-30 11:29:53 +00:00
parent 18bc1c2a0b
commit 5e55af41fc
17 changed files with 687 additions and 14 deletions

View File

@ -4,6 +4,13 @@
Rename 'Reflow lines/paragraph' to 'Reflow lines/block' because in Rename 'Reflow lines/paragraph' to 'Reflow lines/block' because in
future using an indent block is more useful e.g. for ChangeLog future using an indent block is more useful e.g. for ChangeLog
files. files.
* scintilla/LexMarkdown.cxx, scintilla/makefile.win32,
scintilla/include/SciLexer.h, scintilla/include/Scintilla.iface,
scintilla/KeyWords.cxx, scintilla/Makefile.am, src/highlighting.c,
src/about.c, src/filetypes.c, src/filetypes.h, THANKS,
tagmanager/parsers.h, tagmanager/makefile.win32,
tagmanager/markdown.c, tagmanager/Makefile.am, wscript:
Add Markdown filetype (patch by Jon Strait, thanks).
2009-07-29 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com> 2009-07-29 Nick Treleaven <nick(dot)treleaven(at)btinternet(dot)com>

1
THANKS
View File

@ -66,6 +66,7 @@ Simon Treny <simon(dot)treny(at)free(dot)fr> - Documents sidebar stock icons pat
Elias Pschernig <elias(at)users(dot)sourceforge(dot)net> - Recent Projects menu patch Elias Pschernig <elias(at)users(dot)sourceforge(dot)net> - Recent Projects menu patch
Jesse Mayes <plasmasheep(at)gmail(dot)com> - Tango'ish Save All icon Jesse Mayes <plasmasheep(at)gmail(dot)com> - Tango'ish Save All icon
Eugene Arshinov <earshinov(at)gmail(dot)com> - Reload color schemes, split lines KB patches Eugene Arshinov <earshinov(at)gmail(dot)com> - Reload color schemes, split lines KB patches
Jon Strait <jstrait(at)moonloop(dot)net> - Markdown filetype patch
Translators: Translators:
------------ ------------

View File

@ -158,6 +158,7 @@ int Scintilla_LinkLexers() {
LINK_LEXER(lmLatex); LINK_LEXER(lmLatex);
LINK_LEXER(lmLua); LINK_LEXER(lmLua);
LINK_LEXER(lmMake); LINK_LEXER(lmMake);
LINK_LEXER(lmMarkdown);
LINK_LEXER(lmMatlab); LINK_LEXER(lmMatlab);
LINK_LEXER(lmNsis); LINK_LEXER(lmNsis);
LINK_LEXER(lmNull); LINK_LEXER(lmNull);

433
scintilla/LexMarkdown.cxx Normal file
View File

@ -0,0 +1,433 @@
/******************************************************************
* LexMarkdown.cxx
*
* A simple Markdown lexer for scintilla.
*
* Includes highlighting for some extra features from the
* Pandoc implementation; strikeout, using '#.' as a default
* ordered list item marker, and delimited code blocks.
*
* Limitations:
*
* Standard indented code blocks are not highlighted at all,
* as it would conflict with other indentation schemes. Use
* delimited code blocks for blanket highlighting of an
* entire code block. Embedded HTML is not highlighted either.
* Blanket HTML highlighting has issues, because some Markdown
* implementations allow Markdown markup inside of the HTML. Also,
* there is a following blank line issue that can't be ignored,
* explained in the next paragraph. Embedded HTML and code
* blocks would be better supported with language specific
* highlighting; something Scintilla isn't really architected
* to support yet.
*
* The highlighting aims to accurately reflect correct syntax,
* but a few restrictions are relaxed. Delimited code blocks are
* highlighted, even if the line following the code block is not blank.
* Requiring a blank line after a block, breaks the highlighting
* in certain cases, because of the way Scintilla ends up calling
* the lexer.
*
* Written by Jon Strait - jstrait@moonloop.net
*
* This source code is released for free distribution under the
* terms of the GNU General Public License.
*
*****************************************************************/
#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 SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool IsNewline(const int ch) {
return (ch == '\n' || ch == '\r');
}
// True if can follow ch down to the end with possibly trailing whitespace
static bool FollowToLineEnd(const int ch, const int state, const int endPos, StyleContext &sc) {
int i = 0;
while (sc.GetRelative(++i) == ch)
;
// Skip over whitespace
while (IsASpaceOrTab(sc.GetRelative(i)) && sc.currentPos + i < endPos)
++i;
if (IsNewline(sc.GetRelative(i)) || sc.currentPos + i == endPos) {
sc.Forward(i);
sc.ChangeState(state);
sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
return true;
}
else return false;
}
// Set the state on text section from current to length characters,
// then set the rest until the newline to default, except for any characters matching token
static void SetStateAndZoom(const int state, const int length, const int token, StyleContext &sc) {
int i = 0;
sc.SetState(state);
sc.Forward(length);
sc.SetState(SCE_MARKDOWN_DEFAULT);
sc.Forward();
while (sc.More() && !IsNewline(sc.ch)) {
bool started = false;
if (sc.ch == token && !started) {
sc.SetState(state);
started = true;
}
else if (sc.ch != token) {
sc.SetState(SCE_MARKDOWN_DEFAULT);
started = false;
}
sc.Forward();
}
sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
}
// Does the previous line have more than spaces and tabs?
static bool HasPrevLineContent(StyleContext &sc) {
int i = 0;
// Go back to the previous newline
while ((--i + sc.currentPos) && !IsNewline(sc.GetRelative(i)))
;
while (--i + sc.currentPos) {
if (IsNewline(sc.GetRelative(i)))
break;
if (!IsASpaceOrTab(sc.GetRelative(i)))
return true;
}
return false;
}
static bool IsValidHrule(const int endPos, StyleContext &sc) {
int c, i = 0, count = 1;
while (++i) {
c = sc.GetRelative(i);
if (c == sc.ch)
++count;
// hit a terminating character
else if (!IsASpaceOrTab(c) || sc.currentPos + i == endPos) {
// Are we a valid HRULE
if ((IsNewline(c) || sc.currentPos + i == endPos) &&
count >= 3 && !HasPrevLineContent(sc)) {
sc.SetState(SCE_MARKDOWN_HRULE);
sc.Forward(i);
sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
return true;
}
else {
sc.SetState(SCE_MARKDOWN_DEFAULT);
return false;
}
}
}
}
// Only consume if already valid. Doesn't work for delimiting multiple lines.
static void ConsumeEnd(const int state, const int origPos, const int endPos,
const char *token, StyleContext &sc) {
int targetPos;
while (sc.currentPos + 1 < endPos) {
sc.Forward();
if (sc.Match(token) && sc.chPrev != '\\' && sc.chPrev != ' ') {
targetPos = sc.currentPos + strlen(token);
sc.currentPos = origPos;
sc.SetState(state);
sc.Forward(targetPos - origPos);
sc.SetState(SCE_MARKDOWN_DEFAULT);
break;
}
}
}
static void ColorizeMarkdownDoc(unsigned int startPos, int length, int initStyle,
WordList *keywordlists[], Accessor &styler) {
int digitCount = 0;
int endPos = startPos + length;
int precharCount;
// Don't advance on a new loop iteration and retry at the same position.
// Useful in the corner case of having to start at the beginning file position
// in the default state.
bool freezeCursor = false;
StyleContext sc(startPos, length, initStyle, styler);
while (sc.More()) {
// Skip past escaped characters
if (sc.ch == '\\') {
sc.Forward();
continue;
}
// A blockquotes resets the line semantics
if (sc.state == SCE_MARKDOWN_BLOCKQUOTE)
sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
// Conditional state-based actions
if (sc.state == SCE_MARKDOWN_CODE2) {
if (sc.Match("``") && sc.GetRelative(-2) != ' ') {
sc.Forward(2);
sc.SetState(SCE_MARKDOWN_DEFAULT);
}
}
else if (sc.state == SCE_MARKDOWN_CODE) {
if (sc.ch == '`' && sc.chPrev != ' ')
sc.ForwardSetState(SCE_MARKDOWN_DEFAULT);
}
/* De-activated because it gets in the way of other valid indentation
* schemes, for example multiple paragraphs inside a list item.
// Code block
else if (sc.state == SCE_MARKDOWN_CODEBK) {
bool d = true;
if (IsNewline(sc.ch)) {
if (sc.chNext != '\t') {
for (int c = 1; c < 5; ++c) {
if (sc.GetRelative(c) != ' ')
d = false;
}
}
}
else if (sc.atLineStart) {
if (sc.ch != '\t' ) {
for (int i = 0; i < 4; ++i) {
if (sc.GetRelative(i) != ' ')
d = false;
}
}
}
if (!d)
sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
}
*/
// Strong
else if (sc.state == SCE_MARKDOWN_STRONG1) {
if (sc.Match("**") && sc.chPrev != ' ') {
sc.Forward(2);
sc.SetState(SCE_MARKDOWN_DEFAULT);
}
}
else if (sc.state == SCE_MARKDOWN_STRONG2) {
if (sc.Match("__") && sc.chPrev != ' ') {
sc.Forward(2);
sc.SetState(SCE_MARKDOWN_DEFAULT);
}
}
// Emphasis
else if (sc.state == SCE_MARKDOWN_EM1) {
if (sc.ch == '*' && sc.chPrev != ' ')
sc.ForwardSetState(SCE_MARKDOWN_DEFAULT);
}
else if (sc.state == SCE_MARKDOWN_EM2) {
if (sc.ch == '_' && sc.chPrev != ' ')
sc.ForwardSetState(SCE_MARKDOWN_DEFAULT);
}
else if (sc.state == SCE_MARKDOWN_CODEBK) {
if (sc.atLineStart && sc.Match("~~~")) {
int i = 1;
while (!IsNewline(sc.GetRelative(i)) && sc.currentPos + i < endPos)
i++;
sc.Forward(i);
sc.SetState(SCE_MARKDOWN_DEFAULT);
}
}
else if (sc.state == SCE_MARKDOWN_STRIKEOUT) {
if (sc.Match("~~") && sc.chPrev != ' ') {
sc.Forward(2);
sc.SetState(SCE_MARKDOWN_DEFAULT);
}
}
else if (sc.state == SCE_MARKDOWN_LINE_BEGIN) {
// Header
if (sc.Match("######"))
SetStateAndZoom(SCE_MARKDOWN_HEADER6, 6, '#', sc);
else if (sc.Match("#####"))
SetStateAndZoom(SCE_MARKDOWN_HEADER5, 5, '#', sc);
else if (sc.Match("####"))
SetStateAndZoom(SCE_MARKDOWN_HEADER4, 4, '#', sc);
else if (sc.Match("###"))
SetStateAndZoom(SCE_MARKDOWN_HEADER3, 3, '#', sc);
else if (sc.Match("##"))
SetStateAndZoom(SCE_MARKDOWN_HEADER2, 2, '#', sc);
else if (sc.Match("#")) {
// Catch the special case of an unordered list
if (sc.chNext == '.' && IsASpaceOrTab(sc.GetRelative(2))) {
precharCount = 0;
sc.SetState(SCE_MARKDOWN_PRECHAR);
}
else
SetStateAndZoom(SCE_MARKDOWN_HEADER1, 1, '#', sc);
}
// Code block
else if (sc.Match("~~~")) {
if (!HasPrevLineContent(sc))
sc.SetState(SCE_MARKDOWN_CODEBK);
else
sc.SetState(SCE_MARKDOWN_DEFAULT);
}
else if (sc.ch == '=') {
if (HasPrevLineContent(sc) && FollowToLineEnd('=', SCE_MARKDOWN_HEADER1, endPos, sc))
;
else
sc.SetState(SCE_MARKDOWN_DEFAULT);
}
else if (sc.ch == '-') {
if (HasPrevLineContent(sc) && FollowToLineEnd('-', SCE_MARKDOWN_HEADER2, endPos, sc))
;
else {
precharCount = 0;
sc.SetState(SCE_MARKDOWN_PRECHAR);
}
}
else if (IsNewline(sc.ch))
sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
else {
precharCount = 0;
sc.SetState(SCE_MARKDOWN_PRECHAR);
}
}
// The header lasts until the newline
else if (sc.state == SCE_MARKDOWN_HEADER1 || sc.state == SCE_MARKDOWN_HEADER2 ||
sc.state == SCE_MARKDOWN_HEADER3 || sc.state == SCE_MARKDOWN_HEADER4 ||
sc.state == SCE_MARKDOWN_HEADER5 || sc.state == SCE_MARKDOWN_HEADER6) {
if (IsNewline(sc.ch))
sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
}
// New state only within the initial whitespace
if (sc.state == SCE_MARKDOWN_PRECHAR) {
// Blockquote
if (sc.ch == '>' && precharCount < 5)
sc.SetState(SCE_MARKDOWN_BLOCKQUOTE);
/*
// Begin of code block
else if (!HasPrevLineContent(sc) && (sc.chPrev == '\t' || precharCount >= 4))
sc.SetState(SCE_MARKDOWN_CODEBK);
*/
// HRule - Total of three or more hyphens, asterisks, or underscores
// on a line by themselves
else if ((sc.ch == '-' || sc.ch == '*' || sc.ch == '_') && IsValidHrule(endPos, sc))
;
// Unordered list
else if ((sc.ch == '-' || sc.ch == '*' || sc.ch == '+') && IsASpaceOrTab(sc.chNext)) {
sc.SetState(SCE_MARKDOWN_ULIST_ITEM);
sc.ForwardSetState(SCE_MARKDOWN_DEFAULT);
}
// Ordered list
else if (IsADigit(sc.ch)) {
digitCount = 0;
while (IsADigit(sc.GetRelative(++digitCount)))
;
if (sc.GetRelative(digitCount) == '.' &&
IsASpaceOrTab(sc.GetRelative(digitCount + 1))) {
sc.SetState(SCE_MARKDOWN_OLIST_ITEM);
sc.Forward(digitCount + 1);
sc.SetState(SCE_MARKDOWN_DEFAULT);
}
}
// Alternate Ordered list
else if (sc.ch == '#' && sc.chNext == '.' && IsASpaceOrTab(sc.GetRelative(2))) {
sc.SetState(SCE_MARKDOWN_OLIST_ITEM);
sc.Forward(2);
sc.SetState(SCE_MARKDOWN_DEFAULT);
}
else if (sc.ch != ' ' || precharCount > 2)
sc.SetState(SCE_MARKDOWN_DEFAULT);
else
++precharCount;
}
// New state anywhere in doc
if (sc.state == SCE_MARKDOWN_DEFAULT) {
int origPos = sc.currentPos;
if (sc.atLineStart && sc.ch == '#') {
sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
freezeCursor = true;
}
// Links and Images
if (sc.Match("![") || sc.ch == '[') {
int i = 0, j = 0, k = 0;
int len = endPos - sc.currentPos;
while (i < len && (sc.GetRelative(++i) != ']' || sc.GetRelative(i - 1) == '\\'))
;
if (sc.GetRelative(i) == ']') {
j = i;
if (sc.GetRelative(++i) == '(') {
while (i < len && (sc.GetRelative(++i) != ')' || sc.GetRelative(i - 1) == '\\'))
;
if (sc.GetRelative(i) == ')')
k = i;
}
else if (sc.GetRelative(i) == '[' || sc.GetRelative(++i) == '[') {
while (i < len && (sc.GetRelative(++i) != ']' || sc.GetRelative(i - 1) == '\\'))
;
if (sc.GetRelative(i) == ']')
k = i;
}
}
// At least a link text
if (j) {
sc.SetState(SCE_MARKDOWN_LINK);
sc.Forward(j);
// Also has a URL or reference portion
if (k)
sc.Forward(k - j);
sc.ForwardSetState(SCE_MARKDOWN_DEFAULT);
}
}
// Code - also a special case for alternate inside spacing
if (sc.Match("``") && sc.GetRelative(3) != ' ') {
sc.SetState(SCE_MARKDOWN_CODE2);
sc.Forward();
}
else if (sc.ch == '`' && sc.chNext != ' ') {
sc.SetState(SCE_MARKDOWN_CODE);
}
// Strong
else if (sc.Match("**") && sc.GetRelative(2) != ' ') {
sc.SetState(SCE_MARKDOWN_STRONG1);
sc.Forward();
}
else if (sc.Match("__") && sc.GetRelative(2) != ' ') {
sc.SetState(SCE_MARKDOWN_STRONG2);
sc.Forward();
}
// Emphasis
else if (sc.ch == '*' && sc.chNext != ' ')
sc.SetState(SCE_MARKDOWN_EM1);
else if (sc.ch == '_' && sc.chNext != ' ')
sc.SetState(SCE_MARKDOWN_EM2);
// Strikeout
else if (sc.Match("~~") && sc.GetRelative(2) != ' ') {
sc.SetState(SCE_MARKDOWN_STRIKEOUT);
sc.Forward();
}
// Beginning of line
else if (IsNewline(sc.ch))
sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
}
// Advance if not holding back the cursor for this iteration.
if (!freezeCursor)
sc.Forward();
freezeCursor = false;
}
sc.Complete();
}
LexerModule lmMarkdown(SCLEX_MARKDOWN, ColorizeMarkdownDoc, "markdown");

View File

@ -19,10 +19,10 @@ LexD.cxx \
LexFortran.cxx \ LexFortran.cxx \
LexHaskell.cxx \ LexHaskell.cxx \
LexHTML.cxx \ LexHTML.cxx \
LexYAML.cxx \
LexLua.cxx \ LexLua.cxx \
LexNsis.cxx \ LexMarkdown.cxx \
LexMatlab.cxx \ LexMatlab.cxx \
LexNsis.cxx \
LexOthers.cxx \ LexOthers.cxx \
LexPascal.cxx \ LexPascal.cxx \
LexPerl.cxx \ LexPerl.cxx \
@ -31,7 +31,8 @@ LexR.cxx \
LexRuby.cxx \ LexRuby.cxx \
LexSQL.cxx \ LexSQL.cxx \
LexTCL.cxx \ LexTCL.cxx \
LexVHDL.cxx LexVHDL.cxx \
LexYAML.cxx
SRCS= \ SRCS= \
CallTip.cxx \ CallTip.cxx \

View File

@ -110,6 +110,7 @@
#define SCLEX_POWERPRO 95 #define SCLEX_POWERPRO 95
#define SCLEX_NIMROD 96 #define SCLEX_NIMROD 96
#define SCLEX_SML 97 #define SCLEX_SML 97
#define SCLEX_MARKDOWN 98
#define SCLEX_AUTOMATIC 1000 #define SCLEX_AUTOMATIC 1000
#define SCE_P_DEFAULT 0 #define SCE_P_DEFAULT 0
#define SCE_P_COMMENTLINE 1 #define SCE_P_COMMENTLINE 1
@ -1277,6 +1278,28 @@
#define SCE_MYSQL_USER2 19 #define SCE_MYSQL_USER2 19
#define SCE_MYSQL_USER3 20 #define SCE_MYSQL_USER3 20
#define SCE_MYSQL_HIDDENCOMMAND 21 #define SCE_MYSQL_HIDDENCOMMAND 21
#define SCE_MARKDOWN_DEFAULT 0
#define SCE_MARKDOWN_LINE_BEGIN 1
#define SCE_MARKDOWN_STRONG1 2
#define SCE_MARKDOWN_STRONG2 3
#define SCE_MARKDOWN_EM1 4
#define SCE_MARKDOWN_EM2 5
#define SCE_MARKDOWN_HEADER1 6
#define SCE_MARKDOWN_HEADER2 7
#define SCE_MARKDOWN_HEADER3 8
#define SCE_MARKDOWN_HEADER4 9
#define SCE_MARKDOWN_HEADER5 10
#define SCE_MARKDOWN_HEADER6 11
#define SCE_MARKDOWN_PRECHAR 12
#define SCE_MARKDOWN_ULIST_ITEM 13
#define SCE_MARKDOWN_OLIST_ITEM 14
#define SCE_MARKDOWN_BLOCKQUOTE 15
#define SCE_MARKDOWN_STRIKEOUT 16
#define SCE_MARKDOWN_HRULE 17
#define SCE_MARKDOWN_LINK 18
#define SCE_MARKDOWN_CODE 19
#define SCE_MARKDOWN_CODE2 20
#define SCE_MARKDOWN_CODEBK 21
#define SCE_PO_DEFAULT 0 #define SCE_PO_DEFAULT 0
#define SCE_PO_COMMENT 1 #define SCE_PO_COMMENT 1
#define SCE_PO_MSGID 2 #define SCE_PO_MSGID 2

View File

@ -2135,6 +2135,7 @@ val SCLEX_SORCUS=94
val SCLEX_POWERPRO=95 val SCLEX_POWERPRO=95
val SCLEX_NIMROD=96 val SCLEX_NIMROD=96
val SCLEX_SML=97 val SCLEX_SML=97
val SCLEX_MARKDOWN=98
# When a lexer specifies its language as SCLEX_AUTOMATIC it receives a # When a lexer specifies its language as SCLEX_AUTOMATIC it receives a
# value assigned in sequence from SCLEX_AUTOMATIC+1. # value assigned in sequence from SCLEX_AUTOMATIC+1.
@ -3545,6 +3546,30 @@ val SCE_SML_COMMENT=12
val SCE_SML_COMMENT1=13 val SCE_SML_COMMENT1=13
val SCE_SML_COMMENT2=14 val SCE_SML_COMMENT2=14
val SCE_SML_COMMENT3=15 val SCE_SML_COMMENT3=15
# Lexical state for SCLEX_MARKDOWN
lex Markdown=SCLEX_MARKDOWN SCE_MARKDOWN_
val SCE_MARKDOWN_DEFAULT=0
val SCE_MARKDOWN_LINE_BEGIN=1
val SCE_MARKDOWN_STRONG1=2
val SCE_MARKDOWN_STRONG2=3
val SCE_MARKDOWN_EM1=4
val SCE_MARKDOWN_EM2=5
val SCE_MARKDOWN_HEADER1=6
val SCE_MARKDOWN_HEADER2=7
val SCE_MARKDOWN_HEADER3=8
val SCE_MARKDOWN_HEADER4=9
val SCE_MARKDOWN_HEADER5=10
val SCE_MARKDOWN_HEADER6=11
val SCE_MARKDOWN_PRECHAR=12
val SCE_MARKDOWN_ULIST_ITEM=13
val SCE_MARKDOWN_OLIST_ITEM=14
val SCE_MARKDOWN_BLOCKQUOTE=15
val SCE_MARKDOWN_STRIKEOUT=16
val SCE_MARKDOWN_HRULE=17
val SCE_MARKDOWN_LINK=18
val SCE_MARKDOWN_CODE=19
val SCE_MARKDOWN_CODE2=20
val SCE_MARKDOWN_CODEBK=21
# Events # Events

View File

@ -61,7 +61,8 @@ MARSHALLER=scintilla-marshal.o
#**LEXOBJS=\\\n\(\*.o \) #**LEXOBJS=\\\n\(\*.o \)
LEXOBJS=\ LEXOBJS=\
LexAda.o LexBash.o LexAsm.o LexCSS.o LexCPP.o LexCrontab.o LexHTML.o LexOthers.o LexPascal.o \ LexAda.o LexBash.o LexAsm.o LexCSS.o LexCPP.o LexCrontab.o LexHTML.o LexOthers.o LexPascal.o \
LexPerl.o LexPython.o LexSQL.o LexCaml.o LexTCL.o LexRuby.o LexFortran.o LexVHDL.o LexMatlab.o \ LexPerl.o LexPython.o LexSQL.o LexCaml.o LexTCL.o LexRuby.o LexFortran.o LexVHDL.o \
LexMarkdown.o LexMatlab.o \
LexD.o LexLua.o LexHaskell.o LexBasic.o LexR.o LexYAML.o LexCmake.o LexNsis.o LexD.o LexLua.o LexHaskell.o LexBasic.o LexR.o LexYAML.o LexCmake.o LexNsis.o
#--Autogenerated -- end of automatically generated section #--Autogenerated -- end of automatically generated section

View File

@ -84,7 +84,7 @@ static const gchar *contributors =
"Chris Macksey, Christoph Berg, Colomban Wendling, Conrad Steenberg, Daniel Richard G., Dave Moore, Dirk Weber, " "Chris Macksey, Christoph Berg, Colomban Wendling, Conrad Steenberg, Daniel Richard G., Dave Moore, Dirk Weber, "
"Elias Pschernig, Eugene Arshinov, Felipe Pena, François Cami, " "Elias Pschernig, Eugene Arshinov, Felipe Pena, François Cami, "
"Giuseppe Torelli, Guillaume de Rorthais, Guillaume Hoffmann, Herbert Voss, Jason Oster, Jean-François Wauthy, Jeff Pohlmeyer, " "Giuseppe Torelli, Guillaume de Rorthais, Guillaume Hoffmann, Herbert Voss, Jason Oster, Jean-François Wauthy, Jeff Pohlmeyer, "
"Jesse Mayes, John Gabriele, Josef Whiter, Kevin Ellwood, Kristoffer A. Tjernås, Marko Peric, Matti Mårds, Moritz Barsnick, " "Jesse Mayes, John Gabriele, Jon Strait, Josef Whiter, Kevin Ellwood, Kristoffer A. Tjernås, Marko Peric, Matti Mårds, Moritz Barsnick, "
"Peter Strand, Philipp Gildein, Pierre Joye, Rob van der Linde, Robert McGinley, Roland Baudin, S Jagannathan, Saleem Abdulrasool, " "Peter Strand, Philipp Gildein, Pierre Joye, Rob van der Linde, Robert McGinley, Roland Baudin, S Jagannathan, Saleem Abdulrasool, "
"Sebastian Kraft, Shiv, Slava Semushin, Stefan Oltmanns, Tamim, Thomas Martitz, Tomás Vírseda, " "Sebastian Kraft, Shiv, Slava Semushin, Stefan Oltmanns, Tamim, Thomas Martitz, Tomás Vírseda, "
"Tyler Mulligan, Walery Studennikov, Yura Siamashka"; "Tyler Mulligan, Walery Studennikov, Yura Siamashka";

View File

@ -341,6 +341,17 @@ static void init_builtin_filetypes(void)
ft->comment_close = NULL; ft->comment_close = NULL;
ft->group = GEANY_FILETYPE_GROUP_COMPILED; ft->group = GEANY_FILETYPE_GROUP_COMPILED;
#define MARKDOWN
ft = filetypes[GEANY_FILETYPES_MARKDOWN];
ft->lang = 36;
ft->name = g_strdup("Markdown");
ft->title = g_strdup_printf(_("%s source file"), "Markdown");
ft->extension = g_strdup("md");
ft->pattern = utils_strv_new("*.mdml", "*.mdwn", "*.markdown", "*.md", NULL);
ft->comment_open = NULL;
ft->comment_close = NULL;
ft->group = GEANY_FILETYPE_GROUP_MISC;
#define SH #define SH
ft = filetypes[GEANY_FILETYPES_SH]; ft = filetypes[GEANY_FILETYPES_SH];
ft->lang = 16; ft->lang = 16;

View File

@ -76,7 +76,7 @@ typedef enum
GEANY_FILETYPES_VHDL, GEANY_FILETYPES_VHDL,
GEANY_FILETYPES_ADA, GEANY_FILETYPES_ADA,
GEANY_FILETYPES_CMAKE, GEANY_FILETYPES_CMAKE,
GEANY_FILETYPES_MARKDOWN,
/* ^ append items here */ /* ^ append items here */
GEANY_MAX_BUILT_IN_FILETYPES /* Don't use this, use filetypes_array->len instead */ GEANY_MAX_BUILT_IN_FILETYPES /* Don't use this, use filetypes_array->len instead */
} }

View File

@ -2725,6 +2725,64 @@ static void styleset_sql(ScintillaObject *sci)
} }
static void styleset_markdown_init(gint ft_id, GKeyFile *config, GKeyFile *config_home)
{
new_style_array(GEANY_FILETYPES_MARKDOWN, 17);
get_keyfile_hex(config, config_home, "default", 0x000000, 0xffffff, FALSE, &style_sets[GEANY_FILETYPES_MARKDOWN].styling[0]);
get_keyfile_hex(config, config_home, "strong", 0xff0000, 0xffffff, FALSE, &style_sets[GEANY_FILETYPES_MARKDOWN].styling[1]);
get_keyfile_hex(config, config_home, "emphasis", 0xff0000, 0xffffff, FALSE, &style_sets[GEANY_FILETYPES_MARKDOWN].styling[2]);
get_keyfile_hex(config, config_home, "header1", 0x0000bb, 0xffffff, FALSE, &style_sets[GEANY_FILETYPES_MARKDOWN].styling[3]);
get_keyfile_hex(config, config_home, "header2", 0x0000bb, 0xffffff, FALSE, &style_sets[GEANY_FILETYPES_MARKDOWN].styling[4]);
get_keyfile_hex(config, config_home, "header3", 0x0000bb, 0xffffff, FALSE, &style_sets[GEANY_FILETYPES_MARKDOWN].styling[5]);
get_keyfile_hex(config, config_home, "header4", 0x0000bb, 0xffffff, FALSE, &style_sets[GEANY_FILETYPES_MARKDOWN].styling[6]);
get_keyfile_hex(config, config_home, "header5", 0x0000bb, 0xffffff, FALSE, &style_sets[GEANY_FILETYPES_MARKDOWN].styling[7]);
get_keyfile_hex(config, config_home, "header6", 0x0000bb, 0xffffff, FALSE, &style_sets[GEANY_FILETYPES_MARKDOWN].styling[8]);
get_keyfile_hex(config, config_home, "ulist_item", 0x007f00, 0xffffff, FALSE, &style_sets[GEANY_FILETYPES_MARKDOWN].styling[9]);
get_keyfile_hex(config, config_home, "olist_item", 0x007f00, 0xffffff, FALSE, &style_sets[GEANY_FILETYPES_MARKDOWN].styling[10]);
get_keyfile_hex(config, config_home, "blockquote", 0xff0000, 0xffffff, FALSE, &style_sets[GEANY_FILETYPES_MARKDOWN].styling[11]);
get_keyfile_hex(config, config_home, "strikeout", 0xaa00ff, 0xffffff, FALSE, &style_sets[GEANY_FILETYPES_MARKDOWN].styling[12]);
get_keyfile_hex(config, config_home, "hrule", 0xff901e, 0xffffff, FALSE, &style_sets[GEANY_FILETYPES_MARKDOWN].styling[13]);
get_keyfile_hex(config, config_home, "link", 0x0000ff, 0xffffff, FALSE, &style_sets[GEANY_FILETYPES_MARKDOWN].styling[14]);
get_keyfile_hex(config, config_home, "code", 0x009f00, 0xffffff, FALSE, &style_sets[GEANY_FILETYPES_MARKDOWN].styling[15]);
get_keyfile_hex(config, config_home, "codebk", 0x005f00, 0xffffff, FALSE, &style_sets[GEANY_FILETYPES_MARKDOWN].styling[16]);
style_sets[GEANY_FILETYPES_MARKDOWN].keywords = NULL;
get_keyfile_wordchars(config, config_home, &style_sets[GEANY_FILETYPES_MARKDOWN].wordchars);
}
static void styleset_markdown(ScintillaObject *sci)
{
const filetype_id ft_id = GEANY_FILETYPES_MARKDOWN;
apply_filetype_properties(sci, SCLEX_MARKDOWN, ft_id);
set_sci_style(sci, STYLE_DEFAULT, GEANY_FILETYPES_MARKDOWN, 0);
set_sci_style(sci, SCE_MARKDOWN_DEFAULT, GEANY_FILETYPES_MARKDOWN, 0);
set_sci_style(sci, SCE_MARKDOWN_LINE_BEGIN, GEANY_FILETYPES_MARKDOWN, 0);
set_sci_style(sci, SCE_MARKDOWN_PRECHAR, GEANY_FILETYPES_MARKDOWN, 0);
set_sci_style(sci, SCE_MARKDOWN_STRONG1, GEANY_FILETYPES_MARKDOWN, 1);
set_sci_style(sci, SCE_MARKDOWN_STRONG2, GEANY_FILETYPES_MARKDOWN, 1);
set_sci_style(sci, SCE_MARKDOWN_EM1, GEANY_FILETYPES_MARKDOWN, 2);
set_sci_style(sci, SCE_MARKDOWN_EM2, GEANY_FILETYPES_MARKDOWN, 2);
set_sci_style(sci, SCE_MARKDOWN_HEADER1, GEANY_FILETYPES_MARKDOWN, 3);
set_sci_style(sci, SCE_MARKDOWN_HEADER2, GEANY_FILETYPES_MARKDOWN, 4);
set_sci_style(sci, SCE_MARKDOWN_HEADER3, GEANY_FILETYPES_MARKDOWN, 5);
set_sci_style(sci, SCE_MARKDOWN_HEADER4, GEANY_FILETYPES_MARKDOWN, 6);
set_sci_style(sci, SCE_MARKDOWN_HEADER5, GEANY_FILETYPES_MARKDOWN, 7);
set_sci_style(sci, SCE_MARKDOWN_HEADER6, GEANY_FILETYPES_MARKDOWN, 8);
set_sci_style(sci, SCE_MARKDOWN_ULIST_ITEM, GEANY_FILETYPES_MARKDOWN, 9);
set_sci_style(sci, SCE_MARKDOWN_OLIST_ITEM, GEANY_FILETYPES_MARKDOWN, 10);
set_sci_style(sci, SCE_MARKDOWN_BLOCKQUOTE, GEANY_FILETYPES_MARKDOWN, 11);
set_sci_style(sci, SCE_MARKDOWN_STRIKEOUT, GEANY_FILETYPES_MARKDOWN, 12);
set_sci_style(sci, SCE_MARKDOWN_HRULE, GEANY_FILETYPES_MARKDOWN, 13);
set_sci_style(sci, SCE_MARKDOWN_LINK, GEANY_FILETYPES_MARKDOWN, 14);
set_sci_style(sci, SCE_MARKDOWN_CODE, GEANY_FILETYPES_MARKDOWN, 15);
set_sci_style(sci, SCE_MARKDOWN_CODE2, GEANY_FILETYPES_MARKDOWN, 15);
set_sci_style(sci, SCE_MARKDOWN_CODEBK, GEANY_FILETYPES_MARKDOWN, 16);
}
static void styleset_haskell_init(gint ft_id, GKeyFile *config, GKeyFile *config_home) static void styleset_haskell_init(gint ft_id, GKeyFile *config, GKeyFile *config_home)
{ {
new_style_array(GEANY_FILETYPES_HASKELL, 17); new_style_array(GEANY_FILETYPES_HASKELL, 17);
@ -3599,6 +3657,7 @@ void highlighting_init_styles(gint filetype_idx, GKeyFile *config, GKeyFile *con
init_styleset_case(GEANY_FILETYPES_LUA, styleset_lua_init); init_styleset_case(GEANY_FILETYPES_LUA, styleset_lua_init);
init_styleset_case(GEANY_FILETYPES_MAKE, styleset_makefile_init); init_styleset_case(GEANY_FILETYPES_MAKE, styleset_makefile_init);
init_styleset_case(GEANY_FILETYPES_MATLAB, styleset_matlab_init); init_styleset_case(GEANY_FILETYPES_MATLAB, styleset_matlab_init);
init_styleset_case(GEANY_FILETYPES_MARKDOWN, styleset_markdown_init);
init_styleset_case(GEANY_FILETYPES_NSIS, styleset_nsis_init); init_styleset_case(GEANY_FILETYPES_NSIS, styleset_nsis_init);
init_styleset_case(GEANY_FILETYPES_PASCAL, styleset_pascal_init); init_styleset_case(GEANY_FILETYPES_PASCAL, styleset_pascal_init);
init_styleset_case(GEANY_FILETYPES_PERL, styleset_perl_init); init_styleset_case(GEANY_FILETYPES_PERL, styleset_perl_init);
@ -3660,6 +3719,7 @@ void highlighting_set_styles(ScintillaObject *sci, gint filetype_idx)
styleset_case(GEANY_FILETYPES_LATEX, styleset_latex); styleset_case(GEANY_FILETYPES_LATEX, styleset_latex);
styleset_case(GEANY_FILETYPES_LUA, styleset_lua); styleset_case(GEANY_FILETYPES_LUA, styleset_lua);
styleset_case(GEANY_FILETYPES_MAKE, styleset_makefile); styleset_case(GEANY_FILETYPES_MAKE, styleset_makefile);
styleset_case(GEANY_FILETYPES_MARKDOWN, styleset_markdown);
styleset_case(GEANY_FILETYPES_MATLAB, styleset_matlab); styleset_case(GEANY_FILETYPES_MATLAB, styleset_matlab);
styleset_case(GEANY_FILETYPES_NSIS, styleset_nsis); styleset_case(GEANY_FILETYPES_NSIS, styleset_nsis);
styleset_case(GEANY_FILETYPES_PASCAL, styleset_pascal); styleset_case(GEANY_FILETYPES_PASCAL, styleset_pascal);

View File

@ -51,6 +51,7 @@ libtagmanager_a_SOURCES =\
latex.c\ latex.c\
lregex.c\ lregex.c\
matlab.c\ matlab.c\
markdown.c\
pascal.c\ pascal.c\
perl.c\ perl.c\
rest.c\ rest.c\

View File

@ -43,7 +43,7 @@ $(COMPLIB): args.o c.o fortran.o make.o conf.o pascal.o perl.o php.o diff.o vhdl
actionscript.o nsis.o \ actionscript.o nsis.o \
haskell.o haxe.o html.o python.o lregex.o rest.o sh.o ctags.o entry.o get.o keyword.o nestlevel.o \ haskell.o haxe.o html.o python.o lregex.o rest.o sh.o ctags.o entry.o get.o keyword.o nestlevel.o \
options.o \ options.o \
parse.o basic.o read.o sort.o strlist.o latex.o matlab.o docbook.o tcl.o ruby.o asm.o sql.o css.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 css.o \
vstring.o regex.o tm_workspace.o tm_work_object.o tm_source_file.o tm_project.o tm_tag.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
$(AR) rc $@ $^ $(AR) rc $@ $^

105
tagmanager/markdown.c Normal file
View File

@ -0,0 +1,105 @@
/*
*
* Copyright (c) 2009, Jon Strait
*
* 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 Markdown files.
*/
/*
* INCLUDE FILES
*/
#include "general.h" /* must always come first */
#include <ctype.h>
#include <string.h>
#include "parse.h"
#include "read.h"
#include "vstring.h"
/*
* DATA DEFINITIONS
*/
static kindOption MarkdownKinds[] = {
{ TRUE, 'v', "variable", "sections" }
};
/*
* FUNCTION DEFINITIONS
*/
/* checks if str is all the same character */
static boolean issame(const char *str)
{
char first = *str;
while (*(++str))
{
if (*str && *str != first)
return FALSE;
}
return TRUE;
}
static void makeMarkdownTag (const vString* const name, boolean name_before)
{
tagEntryInfo e;
initTagEntry (&e, vStringValue(name));
if (name_before)
e.lineNumber--; /* we want the line before the underline chars */
e.kindName = "variable";
e.kind = 'v';
makeTagEntry(&e);
}
static void findMarkdownTags (void)
{
vString *name = vStringNew();
const unsigned char *line;
while ((line = fileReadLine()) != NULL)
{
int name_len = vStringLength(name);
/* underlines must be the same length or more */
if (name_len > 0 && (line[0] == '=' || line[0] == '-') && issame((const char*) line))
{
makeMarkdownTag(name, TRUE);
}
else if (line[0] == '#') {
vStringClear(name);
vStringCatS(name, (const char *) line);
vStringTerminate(name);
makeMarkdownTag(name, FALSE);
}
else {
vStringClear (name);
if (! isspace(*line))
vStringCatS(name, (const char*) line);
vStringTerminate(name);
}
}
vStringDelete (name);
}
extern parserDefinition* MarkdownParser (void)
{
static const char *const patterns [] = { "*.md", NULL };
static const char *const extensions [] = { "md", NULL };
parserDefinition* const def = parserNew ("Markdown");
def->kinds = MarkdownKinds;
def->kindCount = KIND_COUNT (MarkdownKinds);
def->patterns = patterns;
def->extensions = extensions;
def->parser = findMarkdownTags;
return def;
}

View File

@ -50,8 +50,8 @@
MatlabParser, \ MatlabParser, \
ValaParser, \ ValaParser, \
ActionScriptParser, \ ActionScriptParser, \
NsisParser NsisParser, \
MarkdownParser
/* /*
langType of each parser langType of each parser
0 CParser 0 CParser
@ -90,6 +90,7 @@ langType of each parser
33 ValaParser 33 ValaParser
34 ActionScriptParser 34 ActionScriptParser
35 NsisParser 35 NsisParser
36 MarkdownParser
*/ */
#endif /* _PARSERS_H */ #endif /* _PARSERS_H */

13
wscript
View File

@ -58,7 +58,7 @@ tagmanager_sources = [
'tagmanager/docbook.c', 'tagmanager/entry.c', 'tagmanager/fortran.c', 'tagmanager/get.c', 'tagmanager/docbook.c', 'tagmanager/entry.c', 'tagmanager/fortran.c', 'tagmanager/get.c',
'tagmanager/haskell.c', 'tagmanager/haxe.c', 'tagmanager/html.c', 'tagmanager/js.c', 'tagmanager/haskell.c', 'tagmanager/haxe.c', 'tagmanager/html.c', 'tagmanager/js.c',
'tagmanager/keyword.c', 'tagmanager/latex.c', 'tagmanager/lregex.c', 'tagmanager/lua.c', 'tagmanager/keyword.c', 'tagmanager/latex.c', 'tagmanager/lregex.c', 'tagmanager/lua.c',
'tagmanager/make.c', 'tagmanager/matlab.c', 'tagmanager/nsis.c', 'tagmanager/make.c', 'tagmanager/markdown.c', 'tagmanager/matlab.c', 'tagmanager/nsis.c',
'tagmanager/nestlevel.c', 'tagmanager/options.c', 'tagmanager/nestlevel.c', 'tagmanager/options.c',
'tagmanager/parse.c', 'tagmanager/pascal.c', 'tagmanager/parse.c', 'tagmanager/pascal.c',
'tagmanager/perl.c', 'tagmanager/php.c', 'tagmanager/python.c', 'tagmanager/read.c', 'tagmanager/perl.c', 'tagmanager/php.c', 'tagmanager/python.c', 'tagmanager/read.c',
@ -73,15 +73,18 @@ scintilla_sources = [
'scintilla/CharClassify.cxx', 'scintilla/ContractionState.cxx', 'scintilla/Decoration.cxx', 'scintilla/CharClassify.cxx', 'scintilla/ContractionState.cxx', 'scintilla/Decoration.cxx',
'scintilla/DocumentAccessor.cxx', 'scintilla/Document.cxx', 'scintilla/Editor.cxx', 'scintilla/DocumentAccessor.cxx', 'scintilla/Document.cxx', 'scintilla/Editor.cxx',
'scintilla/ExternalLexer.cxx', 'scintilla/Indicator.cxx', 'scintilla/KeyMap.cxx', 'scintilla/ExternalLexer.cxx', 'scintilla/Indicator.cxx', 'scintilla/KeyMap.cxx',
'scintilla/KeyWords.cxx', 'scintilla/LexAda.cxx', 'scintilla/LexAsm.cxx', 'scintilla/LexBash.cxx', 'scintilla/KeyWords.cxx',
'scintilla/LexAda.cxx', 'scintilla/LexAsm.cxx', 'scintilla/LexBash.cxx',
'scintilla/LexBasic.cxx', 'scintilla/LexCaml.cxx', 'scintilla/LexCmake.cxx', 'scintilla/LexCPP.cxx', 'scintilla/LexBasic.cxx', 'scintilla/LexCaml.cxx', 'scintilla/LexCmake.cxx', 'scintilla/LexCPP.cxx',
'scintilla/LexCrontab.cxx', 'scintilla/LexCSS.cxx', 'scintilla/LexD.cxx', 'scintilla/LexCrontab.cxx', 'scintilla/LexCSS.cxx', 'scintilla/LexD.cxx',
'scintilla/LexFortran.cxx', 'scintilla/LexHaskell.cxx', 'scintilla/LexHTML.cxx', 'scintilla/LexFortran.cxx', 'scintilla/LexHaskell.cxx', 'scintilla/LexHTML.cxx',
'scintilla/LexLua.cxx', 'scintilla/LexNsis.cxx', 'scintilla/LexOthers.cxx', 'scintilla/LexLua.cxx', 'scintilla/LexMarkdown.cxx', 'scintilla/LexMatlab.cxx',
'scintilla/LexNsis.cxx', 'scintilla/LexOthers.cxx',
'scintilla/LexPascal.cxx', 'scintilla/LexPerl.cxx', 'scintilla/LexPython.cxx', 'scintilla/LexPascal.cxx', 'scintilla/LexPerl.cxx', 'scintilla/LexPython.cxx',
'scintilla/LexR.cxx', 'scintilla/LexMatlab.cxx', 'scintilla/LexYAML.cxx', 'scintilla/LexR.cxx',
'scintilla/LexRuby.cxx', 'scintilla/LexSQL.cxx', 'scintilla/LexTCL.cxx', 'scintilla/LexRuby.cxx', 'scintilla/LexSQL.cxx', 'scintilla/LexTCL.cxx',
'scintilla/LexVHDL.cxx', 'scintilla/LineMarker.cxx', 'scintilla/PerLine.cxx', 'scintilla/LexVHDL.cxx', 'scintilla/LexYAML.cxx',
'scintilla/LineMarker.cxx', 'scintilla/PerLine.cxx',
'scintilla/PlatGTK.cxx', 'scintilla/PlatGTK.cxx',
'scintilla/PositionCache.cxx', 'scintilla/PropSet.cxx', 'scintilla/RESearch.cxx', 'scintilla/PositionCache.cxx', 'scintilla/PropSet.cxx', 'scintilla/RESearch.cxx',
'scintilla/RunStyles.cxx', 'scintilla/ScintillaBase.cxx', 'scintilla/ScintillaGTK.cxx', 'scintilla/RunStyles.cxx', 'scintilla/ScintillaBase.cxx', 'scintilla/ScintillaGTK.cxx',