Index: scintilla/LexYAML.cxx
===================================================================
--- scintilla/LexYAML.cxx	(revision 0)
+++ scintilla/LexYAML.cxx	(revision 0)
@@ -0,0 +1,314 @@
+// Scintilla source code edit control
+/** @file LexYAML.cxx
+ ** Lexer for YAML.
+ **/
+// Copyright 2003- by Sean O'Dell <sean@celsoft.com>
+// Release under the same license as Scintilla/SciTE.
+
+#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 const char * const yamlWordListDesc[] = {
+	"Keywords",
+	0
+};
+
+static inline bool AtEOL(Accessor &styler, unsigned int i) {
+	return (styler[i] == '\n') ||
+		((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n'));
+}
+
+static unsigned int SpaceCount(char* lineBuffer) {
+	if (lineBuffer == NULL)
+		return 0;
+
+	char* headBuffer = lineBuffer;
+
+	while (*headBuffer == ' ')
+		headBuffer++;
+
+	return headBuffer - lineBuffer;
+}
+
+#define YAML_STATE_BITSIZE 16
+#define YAML_STATE_MASK			(0xFFFF0000)
+#define YAML_STATE_DOCUMENT		(1 << YAML_STATE_BITSIZE)
+#define YAML_STATE_VALUE			(2 << YAML_STATE_BITSIZE)
+#define YAML_STATE_COMMENT		(3 << YAML_STATE_BITSIZE)
+#define YAML_STATE_TEXT_PARENT	(4 << YAML_STATE_BITSIZE)
+#define YAML_STATE_TEXT			(5 << YAML_STATE_BITSIZE)
+
+static void ColouriseYAMLLine(
+	char *lineBuffer,
+	unsigned int currentLine,
+	unsigned int lengthLine,
+	unsigned int startLine,
+	unsigned int endPos,
+	WordList &keywords,
+	Accessor &styler) {
+
+	unsigned int i = 0;
+	bool bInQuotes = false;
+	unsigned int indentAmount = SpaceCount(lineBuffer);
+
+	if (currentLine > 0) {
+		int parentLineState = styler.GetLineState(currentLine - 1);
+
+		if ((parentLineState&YAML_STATE_MASK) == YAML_STATE_TEXT || (parentLineState&YAML_STATE_MASK) == YAML_STATE_TEXT_PARENT) {
+			unsigned int parentIndentAmount = parentLineState&(~YAML_STATE_MASK);
+			if (indentAmount > parentIndentAmount) {
+				styler.SetLineState(currentLine, YAML_STATE_TEXT | parentIndentAmount);
+				styler.ColourTo(endPos, SCE_YAML_TEXT);
+				return;
+			}
+		}
+	}
+	styler.SetLineState(currentLine, 0);
+	if (strncmp(lineBuffer, "---", 3) == 0) {	// Document marker
+		styler.SetLineState(currentLine, YAML_STATE_DOCUMENT);
+		styler.ColourTo(endPos, SCE_YAML_DOCUMENT);
+		return;
+	}
+	// Skip initial spaces
+	while ((i < lengthLine) && lineBuffer[i] == ' ') { // YAML always uses space, never TABS or anything else
+		i++;
+	}
+	if (lineBuffer[i] == '\t') { // if we skipped all spaces, and we are NOT inside a text block, this is wrong
+		styler.ColourTo(endPos, SCE_YAML_ERROR);
+		return;
+	}
+	if (lineBuffer[i] == '#') {	// Comment
+		styler.SetLineState(currentLine, YAML_STATE_COMMENT);
+		styler.ColourTo(endPos, SCE_YAML_COMMENT);
+		return;
+	}
+	while (i < lengthLine) {
+		if (lineBuffer[i] == '\'' || lineBuffer[i] == '\"') {
+			bInQuotes = !bInQuotes;
+		} else if (lineBuffer[i] == ':' && !bInQuotes) {
+			styler.ColourTo(startLine + i - 1, SCE_YAML_IDENTIFIER);
+			styler.ColourTo(startLine + i, SCE_YAML_OPERATOR);
+			// Non-folding scalar
+			i++;
+			while ((i < lengthLine) && isspacechar(lineBuffer[i]))
+				i++;
+			unsigned int endValue = lengthLine - 1;
+			while ((endValue >= i) && isspacechar(lineBuffer[endValue]))
+				endValue--;
+			lineBuffer[endValue + 1] = '\0';
+			if (lineBuffer[i] == '|' || lineBuffer[i] == '>') {
+				i++;
+				if (lineBuffer[i] == '+' || lineBuffer[i] == '-')
+					i++;
+				while ((i < lengthLine) && isspacechar(lineBuffer[i]))
+					i++;
+				if (lineBuffer[i] == '\0') {
+					styler.SetLineState(currentLine, YAML_STATE_TEXT_PARENT | indentAmount);
+					styler.ColourTo(endPos, SCE_YAML_DEFAULT);
+					return;
+				} else if (lineBuffer[i] == '#') {
+					styler.SetLineState(currentLine, YAML_STATE_TEXT_PARENT | indentAmount);
+					styler.ColourTo(startLine + i - 1, SCE_YAML_DEFAULT);
+					styler.ColourTo(endPos, SCE_YAML_COMMENT);
+					return;
+				} else {
+					styler.ColourTo(endPos, SCE_YAML_ERROR);
+					return;
+				}
+			} else if (lineBuffer[i] == '#') {
+				styler.ColourTo(startLine + i - 1, SCE_YAML_DEFAULT);
+				styler.ColourTo(endPos, SCE_YAML_COMMENT);
+				return;
+			}
+			styler.SetLineState(currentLine, YAML_STATE_VALUE);
+			if (lineBuffer[i] == '&' || lineBuffer[i] == '*') {
+				styler.ColourTo(endPos, SCE_YAML_REFERENCE);
+				return;
+			}
+			if (keywords.InList(&lineBuffer[i])) { // Convertible value (true/false, etc.)
+				styler.ColourTo(endPos, SCE_YAML_KEYWORD);
+				return;
+			} else {
+				unsigned int i2 = i;
+				while ((i < lengthLine) && lineBuffer[i]) {
+					if (!(isascii(lineBuffer[i]) && isdigit(lineBuffer[i])) && lineBuffer[i] != '-' && lineBuffer[i] != '.' && lineBuffer[i] != ',') {
+						styler.ColourTo(endPos, SCE_YAML_DEFAULT);
+						return;
+					}
+					i++;
+				}
+				if (i > i2) {
+					styler.ColourTo(endPos, SCE_YAML_NUMBER);
+					return;
+				}
+			}
+			break; // shouldn't get here, but just in case, the rest of the line is coloured the default
+		}
+		i++;
+	}
+	styler.ColourTo(endPos, SCE_YAML_DEFAULT);
+}
+
+static void ColouriseYAMLDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) {
+	char lineBuffer[1024];
+	styler.StartAt(startPos);
+	styler.StartSegment(startPos);
+	unsigned int linePos = 0;
+	unsigned int startLine = startPos;
+	unsigned int endPos = startPos + length;
+	unsigned int maxPos = styler.Length();
+	unsigned int lineCurrent = styler.GetLine(startPos);
+
+	for (unsigned int i = startPos; i < maxPos && i < endPos; i++) {
+		lineBuffer[linePos++] = styler[i];
+		if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
+			// End of line (or of line buffer) met, colourise it
+			lineBuffer[linePos] = '\0';
+			ColouriseYAMLLine(lineBuffer, lineCurrent, linePos, startLine, i, *keywordLists[0], styler);
+			linePos = 0;
+			startLine = i + 1;
+			lineCurrent++;
+		}
+	}
+	if (linePos > 0) {	// Last line does not have ending characters
+		ColouriseYAMLLine(lineBuffer, lineCurrent, linePos, startLine, startPos + length - 1, *keywordLists[0], styler);
+	}
+}
+
+static bool IsCommentLine(int line, Accessor &styler) {
+	int pos = styler.LineStart(line);
+	if (styler[pos] == '#')
+		return true;
+	return false;
+}
+
+static void FoldYAMLDoc(unsigned int startPos, int length, int /*initStyle - unused*/,
+                      WordList *[], Accessor &styler) {
+	const int maxPos = startPos + length;
+	const int maxLines = styler.GetLine(maxPos - 1);             // Requested last line
+	const int docLines = styler.GetLine(styler.Length() - 1);  // Available last line
+	const bool foldComment = styler.GetPropertyInt("fold.comment.yaml") != 0;
+
+	// Backtrack to previous non-blank line so we can determine indent level
+	// for any white space lines
+	// and so we can fix any preceding fold level (which is why we go back
+	// at least one line in all cases)
+	int spaceFlags = 0;
+	int lineCurrent = styler.GetLine(startPos);
+	int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
+	while (lineCurrent > 0) {
+		lineCurrent--;
+		indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
+		if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG) &&
+		        (!IsCommentLine(lineCurrent, styler)))
+			break;
+	}
+	int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;
+
+	// Set up initial loop state
+	int prevComment = 0;
+	if (lineCurrent >= 1)
+		prevComment = foldComment && IsCommentLine(lineCurrent - 1, styler);
+
+	// Process all characters to end of requested range
+	// or comment that hangs over the end of the range.  Cap processing in all cases
+	// to end of document (in case of unclosed comment at end).
+	while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) || prevComment)) {
+
+		// Gather info
+		int lev = indentCurrent;
+		int lineNext = lineCurrent + 1;
+		int indentNext = indentCurrent;
+		if (lineNext <= docLines) {
+			// Information about next line is only available if not at end of document
+			indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL);
+	}
+		const int comment = foldComment && IsCommentLine(lineCurrent, styler);
+		const int comment_start = (comment && !prevComment && (lineNext <= docLines) &&
+		                           IsCommentLine(lineNext, styler) && (lev > SC_FOLDLEVELBASE));
+		const int comment_continue = (comment && prevComment);
+		if (!comment)
+			indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;
+		if (indentNext & SC_FOLDLEVELWHITEFLAG)
+			indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel;
+
+		if (comment_start) {
+			// Place fold point at start of a block of comments
+			lev |= SC_FOLDLEVELHEADERFLAG;
+		} else if (comment_continue) {
+			// Add level to rest of lines in the block
+			lev = lev + 1;
+		}
+
+		// Skip past any blank lines for next indent level info; we skip also
+		// comments (all comments, not just those starting in column 0)
+		// which effectively folds them into surrounding code rather
+		// than screwing up folding.
+
+		while ((lineNext < docLines) &&
+		        ((indentNext & SC_FOLDLEVELWHITEFLAG) ||
+		         (lineNext <= docLines && IsCommentLine(lineNext, styler)))) {
+
+			lineNext++;
+			indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL);
+		}
+
+		const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK;
+		const int levelBeforeComments = Platform::Maximum(indentCurrentLevel,levelAfterComments);
+
+		// Now set all the indent levels on the lines we skipped
+		// Do this from end to start.  Once we encounter one line
+		// which is indented more than the line after the end of
+		// the comment-block, use the level of the block before
+
+		int skipLine = lineNext;
+		int skipLevel = levelAfterComments;
+
+		while (--skipLine > lineCurrent) {
+			int skipLineIndent = styler.IndentAmount(skipLine, &spaceFlags, NULL);
+
+			if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments)
+				skipLevel = levelBeforeComments;
+
+			int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG;
+
+			styler.SetLevel(skipLine, skipLevel | whiteFlag);
+		}
+
+		// Set fold header on non-comment line
+		if (!comment && !(indentCurrent & SC_FOLDLEVELWHITEFLAG) ) {
+			if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK))
+				lev |= SC_FOLDLEVELHEADERFLAG;
+		}
+
+		// Keep track of block comment state of previous line
+		prevComment = comment_start || comment_continue;
+
+		// Set fold level for this line and move to next line
+		styler.SetLevel(lineCurrent, lev);
+		indentCurrent = indentNext;
+		lineCurrent = lineNext;
+	}
+
+	// NOTE: Cannot set level of last line here because indentCurrent doesn't have
+	// header flag set; the loop above is crafted to take care of this case!
+	//styler.SetLevel(lineCurrent, indentCurrent);
+}
+
+LexerModule lmYAML(SCLEX_YAML, ColouriseYAMLDoc, "yaml", FoldYAMLDoc, yamlWordListDesc);
Index: scintilla/Makefile.am
===================================================================
--- scintilla/Makefile.am	(revision 3259)
+++ scintilla/Makefile.am	(working copy)
@@ -17,6 +17,7 @@
 LexFortran.cxx \
 LexHaskell.cxx \
 LexHTML.cxx \
+LexYAML.cxx \
 LexLua.cxx \
 LexOMS.cxx \
 LexMatlab.cxx \
Index: src/filetypes.c
===================================================================
--- src/filetypes.c	(revision 3259)
+++ src/filetypes.c	(working copy)
@@ -517,6 +517,17 @@
 	ft->comment_close = NULL;
 	ft->group = GEANY_FILETYPE_GROUP_SCRIPT;
 
+#define YAML
+	ft = filetypes[GEANY_FILETYPES_YAML];
+	ft->lang = -2;
+	ft->name = g_strdup("YAML");
+	ft->title = g_strdup(_("YAML"));
+	ft->extension = g_strdup("yaml");
+	ft->pattern = utils_strv_new("*.yaml", "*.yml", NULL);
+	ft->comment_open = g_strdup("#");
+	ft->comment_close = NULL;
+	ft->group = GEANY_FILETYPE_GROUP_MISC;
+
 #define ALL
 	ft = filetypes[GEANY_FILETYPES_NONE];
 	ft->lang = -2;
Index: src/filetypes.h
===================================================================
--- src/filetypes.h	(revision 3259)
+++ src/filetypes.h	(working copy)
@@ -72,7 +72,7 @@
 	GEANY_FILETYPES_CSS,
 	GEANY_FILETYPES_DOCBOOK,
 	GEANY_FILETYPES_HTML,
- 	GEANY_FILETYPES_XML,
+	GEANY_FILETYPES_XML,
 
 	/* miscellaneous languages */
 	GEANY_FILETYPES_CONF,
@@ -81,6 +81,7 @@
 	GEANY_FILETYPES_REST,
 	GEANY_FILETYPES_SQL,
 	GEANY_FILETYPES_PO,
+	GEANY_FILETYPES_YAML,
 
 	GEANY_FILETYPES_NONE,	/* must be last filetype */
 	GEANY_MAX_BUILT_IN_FILETYPES	/* Use filetypes_array->len instead */
Index: data/filetypes.yaml
===================================================================
--- data/filetypes.yaml	(revision 0)
+++ data/filetypes.yaml	(revision 0)
@@ -0,0 +1,39 @@
+# For complete documentation of this file, please see Geany's main documentation
+[styling]
+# foreground;background;bold;italic
+html_default=0x000000;0xffffff;false;false
+html_tag=0x000099;0xffffff;false;false
+html_tagunknown=0xff0000;0xffffff;false;false
+html_attribute=0x007f00;0xffffff;false;false
+html_attributeunknown=0xff0000;0xffffff;false;false
+html_number=0x800080;0xffffff;false;false
+html_doublestring=0xff901e;0xffffff;false;false
+html_singlestring=0xff901e;0xffffff;false;false
+html_other=0x800080;0xffffff;false;false
+html_comment=0x808080;0xffffff;false;false
+html_entity=0x800080;0xffffff;false;false
+html_tagend=0x000080;0xffffff;false;false
+[settings]
+# default extension used when saving files
+extension=yaml
+
+# 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=
+# this is an alternative way, so multiline comments are used
+#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=
Index: data/filetype_extensions.conf
===================================================================
--- data/filetype_extensions.conf	(revision 3259)
+++ data/filetype_extensions.conf	(working copy)
@@ -43,4 +43,5 @@
 reStructuredText=*.rest;*.reST;*.rst;
 SQL=*.sql;
 Po=*.po;*.pot;
+YAML=*.yaml;*.yml;
 None=*;
