On Thu, 12 Nov 2009 20:16:53 +0900
Hyoung-Ryul Kang <[email protected]> wrote:

> Thank you for the answer. I understand that the way Geany find a
> folding point is to parse the syntax.
> 
> I wonder if Geany had an option to make a folding point *according to
> the indentation*. This will enable .txt files to be folded in a very
> sensible way. I also think this would not be technically challenging
> too much, since Geany already detects indentation fairly well.
> 
> Some editors like EditPlus (proprietary, www.editplus.com) have that
> option, and it is great to get a neat folded view, not only of the
> code, but also of the results of a program, which often have an
> arbitrary structure.
> 
> Furthermore, you don't even need a syntax file to fold a file of a
> new type, if you only indented it appropriately.
> 
> Maybe I should suggest this as a feature request.
> 
> HR Kang.

Hi. One day I wrote some code to achieve this. I don't think the
attached patch will be accepted (as it's dirty and ugly :-) ), but it
may be useful to someone. The patch is for r4409.

Best regards,
Eugene.
diff --git a/scintilla/LexOthers.cxx b/scintilla/LexOthers.cxx
index 1869014..5103ece 100644
--- a/scintilla/LexOthers.cxx
+++ b/scintilla/LexOthers.cxx
@@ -1271,6 +1271,90 @@ static void ColouriseNullDoc(unsigned int startPos, int length, int, WordList *[
 	}
 }
 
+static void FoldHierarchicalDoc(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 foldCompact = styler.GetPropertyInt("fold.compact") != 0;
+
+	int spaceFlags = 0;
+
+	// Backtrack to previous non-blank line
+
+	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))
+			break;
+	}
+	int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;
+
+	// Process all characters to end of requested range or end of any triple quote
+	// or comment that hangs over the end of the range.  Cap processing in all cases
+	// to end of document (in case of unclosed quote or comment at end).
+	while (lineCurrent <= maxLines) {
+
+		// Gather info
+		int lev = indentCurrent;
+		int lineNext = lineCurrent + 1;
+		int indentNext = indentCurrent;
+		int quote = false;
+		if (lineNext <= docLines) {
+			// Information about next line is only available if not at end of document
+			indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL);
+		}
+		indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;
+		if (indentNext & SC_FOLDLEVELWHITEFLAG)
+			indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel;
+
+		// 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++;
+			indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL);
+		}
+
+		const int levelAfter = indentNext & SC_FOLDLEVELNUMBERMASK;
+		const int levelBefore = Platform::Maximum(indentCurrentLevel, levelAfter);
+
+		// 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 = levelAfter;
+
+		while (--skipLine > lineCurrent) {
+			int skipLineIndent = styler.IndentAmount(skipLine, &spaceFlags, NULL);
+
+			if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfter &&
+					!(skipLineIndent & SC_FOLDLEVELWHITEFLAG))
+				skipLevel = levelBefore;
+
+			styler.SetLevel(skipLine, skipLevel);
+		}
+
+		// Set fold header on non-quote/non-comment line
+		if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
+			if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK))
+				lev |= SC_FOLDLEVELHEADERFLAG;
+		}
+
+		// Set fold level for this line and move to next line
+		styler.SetLevel(lineCurrent, lev);
+		indentCurrent = indentNext;
+		lineCurrent = lineNext;
+	}
+}
+
 LexerModule lmBatch(SCLEX_BATCH, ColouriseBatchDoc, "batch", 0, batchWordListDesc);
 LexerModule lmDiff(SCLEX_DIFF, ColouriseDiffDoc, "diff", FoldDiffDoc, emptyWordListDesc);
 LexerModule lmPo(SCLEX_PO, ColourisePoDoc, "po", 0, emptyWordListDesc);
@@ -1279,3 +1363,4 @@ LexerModule lmMake(SCLEX_MAKEFILE, ColouriseMakeDoc, "makefile", 0, emptyWordLis
 LexerModule lmErrorList(SCLEX_ERRORLIST, ColouriseErrorListDoc, "errorlist", 0, emptyWordListDesc);
 LexerModule lmLatex(SCLEX_LATEX, ColouriseLatexDoc, "latex", 0, emptyWordListDesc);
 LexerModule lmNull(SCLEX_NULL, ColouriseNullDoc, "null");
+LexerModule lmHierarchical(SCLEX_HIERARCHICAL, ColouriseNullDoc, "hierarchical", FoldHierarchicalDoc);
diff --git a/scintilla/include/SciLexer.h b/scintilla/include/SciLexer.h
index 3f68908..1801832 100644
--- a/scintilla/include/SciLexer.h
+++ b/scintilla/include/SciLexer.h
@@ -111,6 +111,7 @@
 #define SCLEX_NIMROD 96
 #define SCLEX_SML 97
 #define SCLEX_MARKDOWN 98
+#define SCLEX_HIERARCHICAL 99
 #define SCLEX_AUTOMATIC 1000
 #define SCE_P_DEFAULT 0
 #define SCE_P_COMMENTLINE 1
diff --git a/src/editor.c b/src/editor.c
index c6ec83a..b400062 100644
--- a/src/editor.c
+++ b/src/editor.c
@@ -4842,6 +4842,7 @@ void editor_set_indentation_guides(GeanyEditor *editor)
 		case SCLEX_PROPERTIES:
 		case SCLEX_FORTRAN: /* Is this the best option for Fortran? */
 		case SCLEX_CAML:
+		case SCLEX_HIERARCHICAL:
 			mode = SC_IV_LOOKFORWARD;
 			break;
 
diff --git a/src/filetypes.c b/src/filetypes.c
index 4842697..3dcc0a8 100644
--- a/src/filetypes.c
+++ b/src/filetypes.c
@@ -638,6 +638,17 @@ static void init_builtin_filetypes(void)
 	ft->comment_open = g_strdup("--");
 	ft->comment_close = NULL;
 	ft->group = GEANY_FILETYPE_GROUP_COMPILED;
+
+#define HIERARCHICAL
+	ft = filetypes[GEANY_FILETYPES_HIERARCHICAL];
+	ft->lang = -2;
+	ft->name = g_strdup(_("Hierarchical"));
+	ft->title = g_strdup(_("Hierarchical"));
+	ft->extension = NULL;
+	ft->pattern = utils_strv_new("*", NULL);
+	ft->comment_open = NULL;
+	ft->comment_close = NULL;
+	ft->group = GEANY_FILETYPE_GROUP_MISC;
 }
 
 
@@ -1621,5 +1632,3 @@ void filetypes_reload(void)
 	foreach_document(i)
 		document_reload_config(documents[i]);
 }
-
-
diff --git a/src/filetypes.h b/src/filetypes.h
index 9d17605..0bb5a59 100644
--- a/src/filetypes.h
+++ b/src/filetypes.h
@@ -83,6 +83,7 @@ typedef enum
 	GEANY_FILETYPES_MARKDOWN,
 	GEANY_FILETYPES_TXT2TAGS,
 	GEANY_FILETYPES_ABC,
+	GEANY_FILETYPES_HIERARCHICAL,
 	/* ^ append items here */
 	GEANY_MAX_BUILT_IN_FILETYPES	/* Don't use this, use filetypes_array->len instead */
 }
diff --git a/src/highlighting.c b/src/highlighting.c
index ecf2ae1..a115dd2 100644
--- a/src/highlighting.c
+++ b/src/highlighting.c
@@ -2039,6 +2039,23 @@ static void styleset_default(ScintillaObject *sci, gint ft_id)
 }
 
 
+static void styleset_hierarchical_init(gint ft_id, GKeyFile *config, GKeyFile *config_home)
+{
+	new_styleset(GEANY_FILETYPES_HIERARCHICAL, 0);
+
+	style_sets[GEANY_FILETYPES_ADA].keywords = g_new(gchar*, 1);
+	style_sets[GEANY_FILETYPES_ADA].keywords[0] = NULL;
+}
+
+
+static void styleset_hierarchical(ScintillaObject *sci)
+{
+	const filetype_id ft_id = GEANY_FILETYPES_HIERARCHICAL;
+
+	apply_filetype_properties(sci, SCLEX_HIERARCHICAL, ft_id);
+}
+
+
 static void styleset_css_init(gint ft_id, GKeyFile *config, GKeyFile *config_home)
 {
 	new_styleset(GEANY_FILETYPES_CSS, 22);
@@ -3270,6 +3287,7 @@ void highlighting_init_styles(gint filetype_idx, GKeyFile *config, GKeyFile *con
 		init_styleset_case(GEANY_FILETYPES_VHDL,	styleset_vhdl_init);
 		init_styleset_case(GEANY_FILETYPES_XML,		styleset_markup_init);
 		init_styleset_case(GEANY_FILETYPES_YAML,	styleset_yaml_init);
+		init_styleset_case(GEANY_FILETYPES_HIERARCHICAL, styleset_hierarchical_init);
 	}
 	/* should be done in filetypes.c really: */
 	if (filetype_idx != GEANY_FILETYPES_NONE)
@@ -3342,6 +3360,7 @@ void highlighting_set_styles(ScintillaObject *sci, GeanyFiletype *ft)
 		styleset_case(GEANY_FILETYPES_VHDL,		styleset_vhdl);
 		styleset_case(GEANY_FILETYPES_XML,		styleset_xml);
 		styleset_case(GEANY_FILETYPES_YAML,		styleset_yaml);
+		styleset_case(GEANY_FILETYPES_HIERARCHICAL,	styleset_hierarchical);
 		case GEANY_FILETYPES_NONE:
 		default:
 			styleset_default(sci, ft->id);
_______________________________________________
Geany mailing list
[email protected]
http://lists.uvena.de/cgi-bin/mailman/listinfo/geany

Reply via email to